1. 程式人生 > >Android查缺補漏(線程篇)-- IntentService的源碼淺析

Android查缺補漏(線程篇)-- IntentService的源碼淺析

per .com 隨著 nds public message 這一 這樣的 系統

本文作者:CodingBlock 文章鏈接:http://www.cnblogs.com/codingblock/p/8975114.html

在Android中有兩個比較容易弄混的概念,Service和Thread,我們都知道這兩個東西都可以執行後臺任務,但要註意的是Service是跑在主線程中的,如果不做特殊處理是會阻塞主線程的,而IntentService正好彌補了這一點,在《Android查缺補漏--Service和IntentService》這篇博文中已經簡單介紹過了IntentService的基本用法,本篇博文會將對IntentService的原理做一個簡單的分析。

一、IntentService的初始化分析

IntentService是一種服務,可以很方便的執行後臺異步任務,采用HandlerThread執行任務,當任務執行完畢後,IntentService自動退出。

相比於普通的Service,IntentService繼承了Service,並在其內部創建了HandlerThread和Handler,其中HandlerThread用於執行耗時任務,可以查看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);
}

通過源碼可以看到,IntentService在onCreate()方法中創建了一個HandlerThread,並為這個HandlerThread綁定了一個Handler(ServiceHandler)。

註:HandlerThread 是一種具有消息循環的線程,在其內部可以使用handler,其底層實現是內部創建了Looper的線程。

二、IntentService啟動任務過程分析

外界首次調用startService方法來啟動IntentService時,就會觸發onCreate()方法,完成上面操作。

當外界每次觸發onStart方法時,就會在此方法裏面通過ServiceHandler向HandlerThread線程發送消息,onStart方法的源碼如下:

@Override
public void onStart(@Nullable Intent intent, int startId) {
    Message msg = mServiceHandler.obtainMessage();
    msg.arg1 = startId;
    msg.obj = intent;
    mServiceHandler.sendMessage(msg);
}

當上面源碼中的mServiceHandler.sendMessage方法發送完消息後,在ServiceHandler的handlerMessage方法中就會調用onHandleIntent方法來執行我們創建的異步任務,當執行完onHandleIntent中的代碼就會使用stopSelf(msg.arg1)嘗試關閉Service。

private final class ServiceHandler extends Handler {
    public ServiceHandler(Looper looper) {
        super(looper);
    }

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

由於HandlerThread只是一個單線程,所以是串行處理任務。

(stopSelf():立即停止服務。stopSelf(int startId):嘗試停止服務,當還有其他消息未處理,會等待其他消息處理完後再關閉)

三、IntentService優勢

  1. 由於IntentService是一個服務,所以在執行後臺任務時不容易被殺死,想比而言單純的開啟一個線程來執行後臺任務,由於這個進程中沒有活動的四大組件,所以非常容易被系統殺死。
  2. 其實在普通的Service中開啟一個線程也能達到IntentService的效果,只是這樣我們用起來更方便,那麽在Service中開啟線程或者使用IntentService相比在Activity中開啟線程有什麽優勢呢?在Activity中開啟了線程後,當退出了Activity時如果線程中的任務沒有執行完畢,線程是不會退出的。而此時再打開同一個Activity又會創建一個新的線程,就是說在Activity中創建的線程不會隨著Activity的銷毀而銷毀,是不可控的。而如果我們在Service中創建了線程,然後如果線程中的任務沒有執行完畢,我們可以讓Service一直運行在後臺去承載這個線程,這樣的話我們以後在想操作這個線程的話就可以在外界通過bindService的方式再綁定這個Service,從而可以控制運行在這個Service中的線程。

本文作者:CodingBlock 文章鏈接:http://www.cnblogs.com/codingblock/p/8975114.html

本文為博客園首發並已同步授權給騰訊雲·雲+社區!

Android查缺補漏(線程篇)-- IntentService的源碼淺析