深刻研究 IntentService 原始碼

當心,AsyncTask 不是萬能的 中,我提到 IntentService 是你在實現下載功能時,最好用的武器之一。html

這次,我們來深刻研究 IntentService 的原始碼,看他是如何用短短幾行代碼,來解決這個問題。java

public abstract class IntentService extends Service {  
      ...  
    }

從 class 的宣告中,你能夠知道 IntentService 就是通常的 Service。android

接著他定義一個 ServiceHandler。通常我們在創建 Handler 時,都是用預設的建構式。預設的 Handler 建構式,是依附在當前的 thread 身上。因此通常開發者都以為 Handler 必定是依附在 main-thread 上,這是不對的觀念。git

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

    這個 ServiceHandler,是依附在一個 non-UI thread 的 Looper 上。Looper 就是訊息迴圈 (message loop),這是 Android UI 在處理各式訊息時,最重要的元件之一。而 ServiceHandler 建構式中所傳入的 Looper 物件,是在 onCreate() 中所創建的。app

      @Override  
      public void onCreate() {  
        super.onCreate();  
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");  
        thread.start();  
        
        mServiceLooper = thread.getLooper();  
        mServiceHandler = new ServiceHandler(mServiceLooper);  
      }

      看到了吧,mServiceLooper 就是 thread 物件中的 Looper 物件。這個 thread 物件就是一個 HandlerThread,他是一個 non-UI thread。async

      因此現在這個 Service,一個帶有 message loop(mServiceLooper) 的 non-UI thread (mServiceHandler) 正一直在背後執行著,監看是否有任何傳入的 message。ide

      接著,每當你呼叫 startService(new Intent(this, MyIntentService.class)) 啟動 IntentService 時,其實他只是很簡單地送出一個 message 到 mServiceHandler 上。oop

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

        我們知道這個 message 最終會由 Handler.handleMessage() 來處理。由於整個 mServiceHandler 是在 non-UI thread 中執行。當他在 handleMessage() 中呼叫你的 onHandleIntent() 時,你的 onHandleIntent() 天然也是在 non-UI thread 中執行。ui

          private final class ServiceHandler extends Handler {  
            ...  
            @Override  
            public void handleMessage(Message msg) {  
              onHandleIntent((Intent)msg.obj);  
              stopSelf(msg.arg1);  
            }  
          }

          onHandleIntent() 執行結束後,接著呼叫 stopSelf(int)。由於 IntentService 是設計用來能夠在一個 Service 中服務多項工做,所以在這裡,不能夠呼叫 stopSelf()。this

          若是你呼叫 startService() 屢次,每一次的呼叫都會被轉成一個 message,並放在 mServiceLooper 的 message queue 中,等待被服務。一個 message 所對應的工做被完成後,才會繼續服務下一個工做。因此,這些等待被服務的工做,並不是一塊兒並行 (Concurrent) 的,而是循序執行。

          當全部的工做都處裡完時,也是 Service 該結束的時候。

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

          在 onDestroy() 中,惟一要作的事,就是要將 mServiceLooper 停下來。

          從研究這個 IntentService 的原始碼,我們能夠學到如何運用簡單的 pattern (Service + Handler + HandlerThread),幫我們更簡易與有系統地,完成我們所想要作的事。

          最後我們先前說過,在 IntentServcie 中等待被服務的工做,並不會被一塊兒並行,而是循序執行。若是你今天想要這些等待被服務的工做,能夠一塊兒被並行,在研讀完這個 IntentService 的原始碼後,你本身知不知道如何寫個可支援並行工做的 IntentService?

          提示:能夠用 Service + AsyncTask 的組合。

          相關文章
          相關標籤/搜索