Android IntentService工作原理

IntentService與普通的Service最大的區(qū)別在于,通過(guò)startService啟動(dòng)的普通Service,如果不主導(dǎo)調(diào)stopService方法,那么這個(gè)service會(huì)在后臺(tái)一直存在。 而通過(guò)startService啟動(dòng)的IntentService,他在執(zhí)行完所有異步任務(wù)后,會(huì)自己銷(xiāo)毀。

通過(guò)查看源碼,我們知道 IntentService 實(shí)際上是繼承了Service類(lèi)的,他與普通Service不同的是,它定義了一個(gè)ServiceLooper和ServiceHandler。


當(dāng)我們啟動(dòng)一個(gè)IntentService的時(shí)候,首先會(huì)進(jìn)入Service的onCreate方法,我們來(lái)看看IntentService在onCreate方法里都做了些什么。

    @Override
    public void onCreate() {
        // TODO: It would be nice to have an option to hold a partial wakelock
        // during processing, and to have a static startService(Context, Intent)
        // method that would launch the service & hand off a wakelock.

        super.onCreate();
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();

        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }

從代碼中可以看到,它創(chuàng)建一個(gè)HandlerThread的線(xiàn)程,然后直接啟動(dòng)這個(gè)線(xiàn)程,
然后再初始化上面說(shuō)的mServiceLooper和mServiceHandler.(如果不知道handler,looper工作原理的自行查閱)。

mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);//handler使用的looper是HandlerThread里的,
//也就是說(shuō)使用該handler發(fā)送的消息都會(huì)到 HandlerThread 的 Looper的 MessageQueue中。

在HandlerThread的run方法中,Looper.loop() 進(jìn)入循環(huán)等待mServiceHandler發(fā)送的消息


image.png

。
當(dāng)有消息會(huì)回調(diào)到mServiceHandler的handleMessage方法中,在這里

        @Override
        public void handleMessage(Message msg) {
            onHandleIntent((Intent)msg.obj);
            stopSelf(msg.arg1);
        }

有一個(gè)抽象方法 onHandleIntent 去處理異步任務(wù),同時(shí)會(huì)調(diào)用stopSelf(msg.arg1);去停止服務(wù),但是這個(gè)服務(wù)不是直接停止,需要等所有的異步任務(wù) 處理完成之后才會(huì)去銷(xiāo)毀自己。 待會(huì)我們用代碼去驗(yàn)證這一點(diǎn)。
當(dāng)IntentService中所有的異步任務(wù)都執(zhí)行完成后,會(huì)銷(xiāo)毀掉。 那我們啟動(dòng)的HandlerThread什么時(shí)候銷(xiāo)毀呢,如果不銷(xiāo)毀每啟動(dòng)一次IntentService創(chuàng)建個(gè)異步線(xiàn)程,那顯然是不合理的。 關(guān)鍵就在于IntentSerice的 onDestory方法。

@Override
    public void onDestroy() {
        mServiceLooper.quit();
    }

對(duì)應(yīng)到looper中的quit方法

    /**
     * Quits the looper.
     * <p>
     * Causes the {@link #loop} method to terminate without processing any
     * more messages in the message queue.
     * </p><p>
     * Any attempt to post messages to the queue after the looper is asked to quit will fail.
     * For example, the {@link Handler#sendMessage(Message)} method will return false.
     * </p><p class="note">
     * Using this method may be unsafe because some messages may not be delivered
     * before the looper terminates.  Consider using {@link #quitSafely} instead to ensure
     * that all pending work is completed in an orderly manner.
     * </p>
     *
     * @see #quitSafely
     */
    public void quit() {
        mQueue.quit(false);
    }

這樣,looper就退出循環(huán)了。HandlerThread run方法執(zhí)行完也就銷(xiāo)毀了。

下面通過(guò)例子來(lái)看,定義一個(gè)IntentService:

public class MyIntentService extends IntentService {

    public MyIntentService(){
        super("MyIntentService");
    }
    /**
     * Creates an IntentService.  Invoked by your subclass's constructor.
     *
     * @param name Used to name the worker thread, important only for debugging.
     */
    public MyIntentService(String name) {
        super(name);
    }

    @Override
    public void onStart(@Nullable Intent intent, int startId) {
        super.onStart(intent, startId);
        Log.i("dx startId",String.valueOf(startId));
    }

    @Override
    protected void onHandleIntent(@Nullable Intent intent) {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Log.i("dx", String.valueOf(Thread.currentThread().getId()));
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.i("dx onDestroy","onDestroy");
    }
}

我們?cè)趏nHandleIntent 讓工作線(xiàn)程停止兩秒來(lái)模擬耗時(shí)任務(wù),然后打印出當(dāng)前工作線(xiàn)程的pid。

在activity中定義一個(gè)圖片的點(diǎn)擊事件,每點(diǎn)擊一次,啟動(dòng)一次IntentService

        imageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this,MyIntentService.class);
                startService(intent);
            }
        });

我們點(diǎn)擊一次。


image.png

可以看到,Service的銷(xiāo)毀是在異步任務(wù)結(jié)束之后才銷(xiāo)毀的。

我們?cè)倏焖龠B續(xù)點(diǎn)擊三次,啟動(dòng)三次Service:

image.png

通過(guò)log我們可以看到,當(dāng)service啟動(dòng)后,如果它還在執(zhí)行異步任務(wù),沒(méi)有銷(xiāo)毀,你再次啟動(dòng)它,他是不會(huì)走onCreate方法的。 因?yàn)檫@三次打印出來(lái)的pid都是同一個(gè),說(shuō)明HandlerThread 還是第一次new出來(lái)的那個(gè)。 當(dāng)過(guò)了6秒,三個(gè)異步任務(wù)都執(zhí)行完之后,我們的IntentService才銷(xiāo)毀。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容