IntentService源碼分析

IntentService繼承了Service並且是一個抽象類,需要創建它的子類才能使用IntentService。它相對Service來說,是一個特殊的Service,它的內部使用HandleThread

來執行服務,任務執行完,IntentService會自動退出。相對於Thread來說,它是一個服務,它的優先級高於線程,不容易被系統回收。

一個面試問題:我要用服務下載apk,是用IntentService,還是Service好?爲什麼?

IntentService與Service都可以執行下載apk的任務。具體的下載代碼可以觀看我的文章:IntentService、Service下載的apk。在回答這可問題之前我們要再次回顧一下Service的概念。Service是一種計算型組件,用於在後臺執行一系列計算任務。Service不是一個線程,儘管它是執行後臺計算的,它是運行在主線程中,耗時的後臺操作仍然需要在單獨的子線程中去執行,所以不要在Service的onStart方法中執行耗時操作,不然會出現Application Not Responding!的異常。而IntentService採用隊列的方式將請求的Intent加入隊列,然後開啓一個線程來處理隊列中的Intent,對於異步的startService請求。IntentService處理完一個後再處理第二個,都是在子線程中,不會阻塞主線程。所以有耗時操作與其在Service裏開啓子線程不如在IntentService中處理耗時操作。

回到主題,繼續分析IntentService。

在IntentService的onCreate()方法中,可以看到它實現了HandleThread 和Handle。

private volatile Looper mServiceLooper;
    private volatile ServiceHandler mServiceHandler;
   @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,獲取到mServiceLooper,mServiceHandler。通過mServiceHandler發送信息會在HandlerThread中執行。每次啓動IntentService,會調用onStartCommand()。IntentService在onStartCommand()方法中處理後臺的Intent。在源碼中onStartCommand調用了onStart():

 @Override
    public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
        onStart(intent, startId);
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    }

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

IntentService通過mServiceHandler發送了一條信息,消息會在HandleThread方法中處理。同時將Intent對象給 ServiceHandler的onHandleIntent方法處理。onHandleIntent是運行在子線程中,可以做耗時操作。另外這裏的Intent對象和外界startService(intent)保持一致,通過它可以獲得外界啓動IntentService傳遞的參數,可以區分具體的後臺任務,對不同的後臺採取不同的處理方式(可以咱參照文章後邊的樣例)。onHandleIntent方法執行完之後,會調用stopSelf(int startId)停止服務。stopSelf()會立即停止服務,stopSelf(int startId)會等待所有信息都處理完後才關閉服務,它在服務關閉前會判斷最近啓動的次數是否與startId相等,相等立即停止服務,不相等不停止服務。

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

//This method is invoked on the worker thread with a request to process.
  @WorkerThread
    protected abstract void onHandleIntent(@Nullable Intent intent);

onHandleIntent是一個抽象方法,需要在子類中實現,它的作用就是區分Intent中的參數來區分任務並執行。在執行完onHandleIntent方法後,如果目前只有一個後臺任務會立刻調用stopSelf(int startId)停止服務。如果有多個,會在onHandleIntent執行完最後一個任務後調用停止服務。每執行一個後臺任務都會啓動一次IntentService,而IntentService內部的信息是通過HandleThread來執行,Handle中的Looper順序處理信息,所以IntentService是順序執行後臺任務的。多後臺任務會按照外界發起的順序排隊執行。

public class DemoIntentService extends IntentService {

    static final String Tag = "DemoIntentService";

    public DemoIntentService() {
        super("demo-intentService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        String action = intent.getStringExtra("test_action");
        Log.e(Tag, "receive action=====" + action);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onDestroy() {
        Log.e(Tag, "onDestroy=====");
        super.onDestroy();
    }
}
public class TestActivity extends Activity {

    BroadcastReceiver receiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
Intent mIntent = new Intent(this, DemoIntentService.class);
        mIntent.putExtra("test_action","action1");
        startService(mIntent);
        mIntent.putExtra("test_action","action2");
        startService(mIntent);
        mIntent.putExtra("test_action","action3");
        startService(mIntent);
    }

}
註冊列表
<service android:name=“.downloadApk.DemoIntentService"/>

打印結果:

05-16 23:53:12.219 18007-18292/? E/DemoIntentService: receive action=====action1

05-16 23:53:13.219 18007-18292/? E/DemoIntentService: receive action=====action2

05-16 23:53:14.219 18007-18292/? E/DemoIntentService: receive action=====action3

05-16 23:53:15.219 18007-18007/? E/DemoIntentService: onDestroy=====

日誌顯示三個後臺任務順序執行,在action3後,執行stopSelf(int startId)。

=====================================>

這是一篇對書筆記,文章內容大多數來自於androdi開發藝術探索,很不錯的一本書。

發佈了34 篇原創文章 · 獲贊 2 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章