這次,我們來深入研究 IntentService 的原始碼,看他是如何用短短幾行代碼,來解決這個問題。
- public abstract class IntentService extends Service {
- ...
- }
接著他定義一個 ServiceHandler。一般我們在創建 Handler 時,都是用預設的建構式。預設的 Handler 建構式,是依附在當前的 thread 身上。所以一般開發者都以為 Handler 一定是依附在 main-thread 上,這是不對的觀念。
- private final class ServiceHandler extends Handler {
- public ServiceHandler(Looper looper) {
- super(looper);
- }
- ...
- }
- @Override
- public void onCreate() {
- super.onCreate();
- HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
- thread.start();
- mServiceLooper = thread.getLooper();
- mServiceHandler = new ServiceHandler(mServiceLooper);
- }
所以現在這個 Service,一個帶有 message loop(mServiceLooper) 的 non-UI thread (mServiceHandler) 正一直在背後執行著,監看是否有任何傳入的 message。
接著,每當你呼叫 startService(new Intent(this, MyIntentService.class)) 啟動 IntentService 時,其實他只是很簡單地送出一個 message 到 mServiceHandler 上。
- @Override
- public void onStart(Intent intent, int startId) {
- Message msg = mServiceHandler.obtainMessage();
- msg.arg1 = startId;
- msg.obj = intent;
- mServiceHandler.sendMessage(msg);
- }
- private final class ServiceHandler extends Handler {
- ...
- @Override
- public void handleMessage(Message msg) {
- onHandleIntent((Intent)msg.obj);
- stopSelf(msg.arg1);
- }
- }
如果你呼叫 startService() 多次,每一次的呼叫都會被轉成一個 message,並放在 mServiceLooper 的 message queue 中,等待被服務。一個 message 所對應的工作被完成後,才會繼續服務下一個工作。所以,這些等待被服務的工作,並不是一起並行 (Concurrent) 的,而是循序執行。
當所有的工作都處裡完時,也是 Service 該結束的時候。
- @Override
- public void onDestroy() {
- mServiceLooper.quit();
- }
從研究這個 IntentService 的原始碼,我們可以學到如何運用簡單的 pattern (Service + Handler + HandlerThread),幫我們更簡易與有系統地,完成我們所想要做的事。
最後我們先前說過,在 IntentServcie 中等待被服務的工作,並不會被一起並行,而是循序執行。如果你今天想要這些等待被服務的工作,能夠一起被並行,在研讀完這個 IntentService 的原始碼後,你自己知不知道如何寫個可支援並行工作的 IntentService?
提示:可以用 Service + AsyncTask 的組合。
資料來源:
http://ysl-paradise.blogspot.com/2010/10/intentservice.html
沒有留言:
張貼留言