亚洲欧美日韩熟女|做爱高潮视频网址|国产一区二区三级片|国产Av中文字幕www.性色av|亚洲婷婷永久免费|国产高清中文字幕|欧美变态网站久re视频精品|人妻AV鲁丝第一页|天堂AV一区二区在线观看|综合 91在线精品

Android Service與IntentService詳解與使用

2023-04-12


一、介紹


Service是一種可在后臺執(zhí)行長時間運行操作而不提供界面的應(yīng)用組件。服務(wù)可由其他應(yīng)用組件啟動,而且即使用戶切換到其他應(yīng)用,服務(wù)仍將在后臺繼續(xù)運行。此外,組件可通過綁定到服務(wù)與之進行交互,甚至是執(zhí)行進程間通信 (IPC)。例如,服務(wù)可在后臺處理網(wǎng)絡(luò)事務(wù)、播放音樂,執(zhí)行文件 I/O 或與內(nèi)容提供程序進行交互。


服務(wù)有三種不同的類型:

前臺:

前臺服務(wù)執(zhí)行一些用戶能注意到的操作。例如,音頻應(yīng)用會使用前臺服務(wù)來播放音頻曲目。前臺服務(wù)必須顯示通知。即使用戶停止與應(yīng)用的交互,前臺服務(wù)仍會繼續(xù)運行。


后臺:

后臺服務(wù)執(zhí)行用戶不會直接注意到的操作。例如,如果應(yīng)用使用某個服務(wù)來壓縮其存儲空間,則此服務(wù)通常是后臺服務(wù)。


綁定:

當(dāng)應(yīng)用組件通過調(diào)用 bindService() 綁定到服務(wù)時,服務(wù)即處于綁定狀態(tài)。綁定服務(wù)會提供客戶端-服務(wù)器接口,以便組件與服務(wù)進行交互、發(fā)送請求、接收結(jié)果,甚至是利用進程間通信 (IPC) 跨進程執(zhí)行這些操作。僅當(dāng)與另一個應(yīng)用組件綁定時,綁定服務(wù)才會運行。多個組件可同時綁定到該服務(wù),但全部取消綁定后,該服務(wù)即會被銷毀。


服務(wù)和線程之間進行選擇

服務(wù)是一種即使用戶未與應(yīng)用交互也可在后臺運行的組件,因此,只有在需要服務(wù)時才應(yīng)創(chuàng)建服務(wù)。


如果您必須在主線程之外執(zhí)行操作,但只在用戶與您的應(yīng)用交互時執(zhí)行此操作,則應(yīng)創(chuàng)建新線程。如果您只是想在 Activity 運行的同時播放一些音樂,則可在 onCreate() 中創(chuàng)建線程,在 onStart() 中啟動線程運行,然后在 onStop() 中停止線程。您還可考慮使用 AsyncTask 或 HandlerThread,而非傳統(tǒng)的 Thread 類


注意:

如果您確實要使用服務(wù),則默認情況下,它仍會在應(yīng)用的主線程中運行,因此,如果服務(wù)執(zhí)行的是密集型或阻止性操作,則您仍應(yīng)在服務(wù)內(nèi)創(chuàng)建新線程。


關(guān)于進程的耗時:

有人會說進程在后臺的耗時是15S,這個時間是怎么來的?這個時間是在Framework中定義的,在包括UI線程和Service的liveLongtime已定義好了,在APP層是無法修改,除非你重新編譯AOSP包,然后燒制一個新的rom,這個已涉及到包的定制。有興趣可以自己查看aosp的源碼


如何創(chuàng)建


如要創(chuàng)建服務(wù),您必須創(chuàng)建 Service 的子類(或使用它的一個現(xiàn)有子類)。在實現(xiàn)中,您必須重寫一些回調(diào)方法,從而處理服務(wù)生命周期的某些關(guān)鍵方面,并提供一種機制將組件綁定到服務(wù)(如適用


onStartCommand()

當(dāng)另一個組件(如 Activity)請求啟動服務(wù)時,系統(tǒng)會通過調(diào)用 startService() 來調(diào)用此方法。執(zhí)行此方法時,服務(wù)即會啟動并可在后臺無限期運行。如果您實現(xiàn)此方法,則在服務(wù)工作完成后,您需負責(zé)通過調(diào)用 stopSelf() 或 stopService() 來停止服務(wù)。



onBind()

當(dāng)另一個組件想要與服務(wù)綁定時,系統(tǒng)會通過調(diào)用 bindService() 來調(diào)用此方法。在此方法的實現(xiàn)中,您必須通過返回 IBinder 提供一個接口,以供客戶端用來與服務(wù)進行通信。請務(wù)必實現(xiàn)此方法;但是,如果您并不希望允許綁定,則應(yīng)返回 null。


onCreate()

首次創(chuàng)建服務(wù)時,系統(tǒng)會(在調(diào)用 onStartCommand() 或 onBind() 之前)調(diào)用此方法來執(zhí)行一次性設(shè)置程序。如果服務(wù)已在運行,則不會調(diào)用此方法。


onDestroy()


當(dāng)不再使用服務(wù)且準(zhǔn)備將其銷毀時,系統(tǒng)會調(diào)用此方法。服務(wù)應(yīng)通過實現(xiàn)此方法來清理任何資源,如線程、注冊的偵聽器、接收器等。這是服務(wù)接收的最后一個調(diào)用。



注意:

如果組件通過調(diào)用startService() 啟動服務(wù)(這會引起對 onStartCommand() 的調(diào)用),則服務(wù)會一直運行,直到其使用 stopSelf() 自行停止運行,或由其他組件通過調(diào)用 stopService() 將其停止為止。


bindService() 來創(chuàng)建服務(wù),且未調(diào)用 onStartCommand(),則服務(wù)只會在該組件與其綁定時運行。當(dāng)該服務(wù)與其所有組件取消綁定后,系統(tǒng)便會將其銷毀。


如何接入:

如要聲明服務(wù),請?zhí)砑? 元素作為 元素的子元素。


服務(wù)的啟動

服務(wù)啟動有兩種方式,startService() 和bindService()


startService:


服務(wù)啟動后,其生命周期即獨立于啟動它的組件。即使系統(tǒng)已銷毀啟動服務(wù)的組件,該服務(wù)仍可在后臺無限期地運行。因此,服務(wù)應(yīng)在其工作完成時通過調(diào)用 stopSelf() 來自行停止運行,或者由另一個組件通過調(diào)用 stopService() 來將其停止


startService后,Service先調(diào)用onCreate(),再調(diào)用onStartCommand,如果該服務(wù)已啟動,再啟動也只會調(diào)用onStartCommand()





var service: Intent = Intent(context, HelloService::class.java)
        bind.btnStart.setOnClickListener {

            startService(service)


        }



當(dāng)服務(wù)被銷毀了,才會重新執(zhí)行oncrete()





var service: Intent = Intent(context, HelloService::class.java)
    

        bind.btnStop.setOnClickListener {
            stopService(service)
        }



如果你是繼承了IntentService,那么將會調(diào)用到onHandleIntent。但是IntentService會自動調(diào)用ondestory()。也就是說,IntentService啟動就是一套流程走完,然后調(diào)用stopSelf()






Fragment和Activity如何讓Service去工作?

知道了Service與IntentService的工作流程,那么我們應(yīng)該了解了如何去讓Service為我們做一些耗時。


Service:



inline fun Service.showToast(msg:String) {Toast.makeText(applicationContext,msg,Toast.LENGTH_SHORT).show()}  
  override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        MyLog.log(TAG, "onStartCommand")


        var bundle = intent?.extras;
        var title=bundle?.getString("title","")
        runOnUiThread {
            showToast(title!!)

        }

        return super.onStartCommand(intent, flags, startId)

    }



var service: Intent = Intent(context, HelloService::class.java)
        var bundle=Bundle();
        bundle.putString("title","nihao")
        service.putExtras(bundle)
        bind.btnStart.setOnClickListener {

            startService(service)


        }



IntentService:



inline fun IntentService.showToast(msg:String) {Toast.makeText(applicationContext,msg,Toast.LENGTH_SHORT).show()}



    override fun onHandleIntent(intent: Intent?) {
        MyLog.log(TAG, "onHandleIntent")

        var bundle = intent?.extras;
        var title=bundle?.getString("title","")
        runOnUiThread {
            showToast(title!!)

        }

    }



這里為類擴展了一個函數(shù)showToast();


但是IntentService,調(diào)用完,就會銷毀。




創(chuàng)建綁定服務(wù):bindService


綁定服務(wù)允許應(yīng)用組件通過調(diào)用 bindService() 與其綁定,從而創(chuàng)建長期連接。此服務(wù)通常不允許組件通過調(diào)用 startService() 來啟動它。


如需與 Activity 和其他應(yīng)用組件中的服務(wù)進行交互,或需要通過進程間通信 (IPC) 向其他應(yīng)用公開某些應(yīng)用功能,則應(yīng)創(chuàng)建綁定服務(wù)。


如要創(chuàng)建綁定服務(wù),您需通過實現(xiàn) onBind() 回調(diào)方法返回 IBinder,從而定義與服務(wù)進行通信的接口。然后,其他應(yīng)用組件可通過調(diào)用 bindService() 來檢索該接口,并開始調(diào)用與服務(wù)相關(guān)的方法。服務(wù)只用于與其綁定的應(yīng)用組件,因此若沒有組件與該服務(wù)綁定,則系統(tǒng)會銷毀該服務(wù)。您不必像通過 onStartCommand() 啟動的服務(wù)那樣,以相同方式停止綁定服務(wù)。



實戰(zhàn):

通過以上我們可以了解到,數(shù)據(jù)的獲取,在onBind獲取。如果想要和其他交互,可以通過IBinder。




override fun onBind(p0: Intent?): IBinder? {
        bind = MyBinder().asBinder()
        bindOne=MyTestBind()
        MyLog.log(TAG, "onBind")

        return bindOne
    }



有人很好奇,這個IBinder如何獲???甚至有人了解AIDL,這個和AIDL有什么?其實Service是一個服務(wù),在Android體系中,所有的service同學(xué)都是通過Binder。又因為Activity歸AMS管理,AMS想要和Service通訊,就需要Binder來接入,我們想要和誰通訊,就需要獲取這個對象的Binder,這就是他的信使,把我們的信息交給信使。


這邊將介紹兩種創(chuàng)建IBinder對象

1.AIDL

直接通過通過快捷鍵new一個。




創(chuàng)建完,刪除里面生成的代碼,寫入自己的代碼,記?。篈IDL是接口,所有在使用要小心,準(zhǔn)好以后,build->make一下項目,IDE會自動創(chuàng)建對象的JAVA文件。如果對AIDL還不懂,可以查下這篇文章:





inner class MyBinder : HelloServiceBinder.Stub() {

        var info: String = ""
        override fun add(msg: String?) {

            showToast("add收到你的${msg}")
            info = msg!!
        }

        override fun getTitle(): String {

            return "我已收到你的${info}"
        }
    }





private inner class MyConnect : ServiceConnection {

        override fun onServiceConnected(component: ComponentName?, bind: IBinder?) {

            if (bind is HelloService.MyBinder) {
                bind.add("onServiceConnected")

                showToast(bind.title)
            } else if (bind is HelloService.MyTestBind) {
                bind.add("發(fā)送消息")
                showToast(bind.getTitle())
            }
        }

        override fun onServiceDisconnected(p0: ComponentName?) {
            showToast("斷開")
        }
    }



這樣,就可以通過IBinder來和service交互。


第二種:繼承Binder

這就很簡單了,直接繼承Binder。




inner class MyTestBind : Binder() {

        var info: String = ""
        fun add(msg: String?) {

            showToast("add收到你的${msg}")
            info = msg!!
        }

        fun getTitle(): String {

            return "我已收到你的${info}"
        }
    }



總結(jié)


1.startService與bindService的對比



2.bindService:可以多次bindService,但是onBind只會調(diào)用一次,但是解綁UNBindService只有一次,否則會報錯。所以在綁定與解綁回調(diào)的時候,可以通過一個字段記錄,方便操作綁定,


本文僅代表作者觀點,版權(quán)歸原創(chuàng)者所有,如需轉(zhuǎn)載請在文中注明來源及作者名字。

免責(zé)聲明:本文系轉(zhuǎn)載編輯文章,僅作分享之用。如分享內(nèi)容、圖片侵犯到您的版權(quán)或非授權(quán)發(fā)布,請及時與我們聯(lián)系進行審核處理或刪除,您可以發(fā)送材料至郵箱:service@tojoy.com