IntentService详解
IntentService是什么?
這篇文章是之前就寫好的,一直沒有整理出來,這幾天有空正好整理發布一下。
我們知道Service可以讓我們在后臺處理一些事情,但是Service實際上也是主線程,所以執行長耗時任務時依然會ANR,只不過ANR觸發時間要比前臺長。一般我們會在Service中開啟一個子線程去完成耗時任務。
而IntentService就是解決這個問題的,它是Service的一個抽象子類,需要實現onHandleIntent,代碼在這個函數中執行。它與Service最大的不同就是默認開啟一個子線程,而onHandleIntent就是在子線程中執行的。
所以IntentService就是一個自帶子線程的Service。
那么它是如何實現的,我們通過它的源碼來簡單分析一下。
線程的創建
IntentService的源碼其實不多,先來看看它的onCreate函數
@Override public void onCreate() {super.onCreate();HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");thread.start();mServiceLooper = thread.getLooper();mServiceHandler = new ServiceHandler(mServiceLooper); }在onCreate中會創建并啟動一個HandlerThread。這個HandlerThread是Thread的一個子類,通過它的源碼可以看到實際上就是默認綁定開啟了looper,它的run函數如下:
@Override public void run() {mTid = Process.myTid();Looper.prepare();synchronized (this) {mLooper = Looper.myLooper();notifyAll();}Process.setThreadPriority(mPriority);onLooperPrepared();Looper.loop();mTid = -1; }可以看到綁定并啟動了一個looper,而它的其他函數則都與looper和handler的操作有關,這里不一一看了。
回到onCreate中,接下來的代碼則是通過HandlerThread的looper創建了一個ServiceHandler,這是一個內部類,源碼如下:
private final class ServiceHandler extends Handler {public ServiceHandler(Looper looper) {super(looper);}@Overridepublic void handleMessage(Message msg) {onHandleIntent((Intent)msg.obj);stopSelf(msg.arg1);} }可以看到在handleMessage中調用了onHandleIntent,這樣函數中的代碼就在這個HandlerThread的子線程中運行。
然后執行了stopSelf函數,這個函數是Service的,用于停止服務的,與context的stopService效果是一樣的。
也就是說IntentService執行onHandleIntent后就會試圖停止服務,但是這里還有一些邏輯,注意傳參是msg.arg1,這個很重要,后面會再詳談。
線程運行
通過上面我們知道,IntentService創建時開啟一個線程并啟動一個looper,并且通過ServiceHandler來執行代碼。但是想要執行onHandleIntent,一定需要sendMessage,那么在哪send的呢?
答案是在Service的start周期中,如下:
@Override public void onStart(@Nullable Intent intent, int startId) {Message msg = mServiceHandler.obtainMessage();msg.arg1 = startId;msg.obj = intent;mServiceHandler.sendMessage(msg); }可以看到在onStart中組合了一個msg并send,這樣就實現了服務一啟動就自動執行onHandleIntent。
注意msg的arg1參數賦值是startId,結合上面所說的就是執行onHandleIntent后會執行stopSelf(startId)。
上面我們說過stopSelf會試圖停止服務,為什么是試圖而不是一定,關鍵就是startId這里。
只有當stopSelf函數的startId與Service當前的startId相同,才會停止服務,主要是針對多次startService的情況。
當我們多次startService的時候,startId會自動遞增,并且保存最后一個startId。
所以多次startService,onHandleIntent會執行多次,因為前幾次執行到stopSelf時startId不同,只有當最后一個執行完后才真正的停止服務。
但是注意,在onBind函數中并沒有sendMessage,所以IntentService需要使用start的方式,bind的方式由于不會走onStart這個周期,所以onHandleIntent不會執行。
退出線程
在創建線程時默認開啟了looper,looper其實就是一個死循環,所以這個線程會一直阻塞。那么IntentService如何退出這個線程?
總結
以上是生活随笔為你收集整理的IntentService详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Preference跳转activity
- 下一篇: 如何发布Android Library到