Android IntentService源碼分析

簡介

Service 是 Android 四大組件之一,用于后臺運行,但由于 Service 依然運行在主線程,所以是不能直接進行耗時操作的。如果有耗時操作,還是需要放到子線程中,可以手動開啟線程,也可以使用 Android 提供的一個非常簡便的類 IntentService 。這個類的源碼還是很簡單的,本文分析一下它的實現。

HandlerThread

在分析 IntentService 之前,先要了解 HandlerThread 。看名字就知道這個類是與 Handler 有關的線程類,API 是這么描述的:

Handy class for starting a new thread that has a looper. The looper can then be used to create handler classes. Note that start() must still be called.

它是為創建附帶 Looper 對象的線程的幫助類。 Looper 對象可用于創建 Handler 類。 當然仍然要調用 start() 來開啟線程。

在上篇文章 Android Handler的原理 中,我們知道一個線程創建 Handler 的時候,必須要有 Looper 對象,利用 Looper 開啟消息循環。在主線程中,系統已經幫我們做了這些工作。那么如果在其它子線程,我們該怎么創建 Looper 呢? 看看 HandlerThread 的 run() 方法:

public void run() {
    mTid = Process.myTid();
    Looper.prepare();
    synchronized (this) {
        mLooper = Looper.myLooper();
        notifyAll();
    }
    Process.setThreadPriority(mPriority);
    onLooperPrepared();
    Looper.loop();
    mTid = -1;
}

在這個方法中調用了 Looper.prepare() 為線程獲取 Looper 對象,并且保存這個對象。接著又調用 Looper.loop() 開啟消息循環,這個方法里面有個無限循環不斷從消息隊列中取出消息,于是這個線程的消息系統便建立起來了。這些在上一篇文章中已經分析過。

IntentService

搞清楚 HandlerThread , IntentService 就很簡單了。 IntentService 內部使用了 HandlerThread 。 IntentService 繼承了 Service 并且是 一個抽象類。下面是它的 onCreate() 方法:

 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);

}

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);
}

} </code></pre>

這個方法里面創建了一個 HandlerThread 對象,并且獲取它的 Looper ,緊接著用這個 Looper 創建了 Handler 。 IntentService 的 handleMessage 方法把接收的消息交給 onHandleIntent 處理,這個方法是一個抽象方法,也是我們使用 IntentService 時需要重寫的方法。 onHandleIntent 處理完成后 IntentService 會調用 stopSelf() 自動停止。 handleMessage 將在 Looper.loop() 方法中被調用,運行在 HandlerThread 中,所以可以安全地處理耗時操作。

消息又是怎么傳過來的呢?看一下 onStartCommand() 的源碼:

public int onStartCommand(Intent intent, int flags, int startId) {
    onStart(intent, startId);
    return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
public void onStart(Intent intent, int startId) {
    Message msg = mServiceHandler.obtainMessage();
    msg.arg1 = startId;
    msg.obj = intent;
    mServiceHandler.sendMessage(msg);
}

很簡單,把 intent 參數包裝到 message 的 obj 中,然后發送消息。這里的 Intent 就是啟動服務時 startService(Intent) 里的 Intent 。

對于 Service 而言,多次調用 startService(Intent) 時, onCreate() 方法只會調用一次,所以在這里面做一些初始化工作,而 onStartCommand 則相應地會調用多次。因此,只要 Intent 的參數不同,便可以完成不同的任務。

總結

從上面的分析可以看出,只要明白 Handler 的原理, IntentService 還是比較好理解的。使用 IntentService 需要注意幾點:

  • 不可以直接和UI做交互。為了把他執行的結果體現在UI上,需要把結果返回給Activity。

  • 工作任務隊列是順序執行的,如果一個任務正在IntentService中執行,此時你再發送一個新的任務請求,這個新的任務會一直等待直到前面一個任務執行完畢才開始執行。

  • 正在執行的任務無法打斷。

來自: https://segmentfault.com/a/1190000004875002

 本文由用戶 aqpp1310 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!