Android查缺補漏(線程篇)-- IntentService的源碼淺析
本文作者: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優勢
- 由於IntentService是一個服務,所以在執行後臺任務時不容易被殺死,想比而言單純的開啟一個線程來執行後臺任務,由於這個進程中沒有活動的四大組件,所以非常容易被系統殺死。
- 其實在普通的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的源碼淺析