IntentService原始碼

wyman_1007發表於2017-12-14

分析的IntentService原始碼為API-25版本

IntentService屬於Service

IntentService繼承自Service,那麼它的結構就和Service一樣。
image.png
這個不需多講。但在使用上與Service有點不同,可以說簡化版的Service。有點類似Handler與AsyTask的關係。

IntentService的使用

Intent serviceIntent = new Intent(this, ParseIntentService.class);
startService(serviceIntent);
複製程式碼

上面程式碼就是開啟一個IntentService服務。開啟之後就不用管理它了。這就是剛才說的簡化版的Service。這篇文章的重點其實就是這裡:IntentService為什麼是簡化的Service
上面的ParseIntentService繼承IntentService,重寫了onHandleIntent()方法。

IntentService原始碼

IntentService的原始碼不多就只有百來行
image.png
解析下這裡的程式碼:
出現Looper和Handler。

  • ServiceHandler handleMessage()方法,呼叫完onHandleIntent();方法後stopSelf()即停止服務。所以上面說IntentService開啟服務後不需要管它,因為它呼叫完ServiceHandler的handleMessage()方法後就會停止服務。
    都知道Handler的handleMessage()不是Handler自己呼叫的,是有傳送資訊,handleMessage()就會被呼叫。那麼現在看看哪裡傳送資訊。

  • Looper 在後面涉及到會介紹

IntentService的onCreate()方法

都知道Service和Activity類似都會有相關生命週期的方法。當上門的程式碼開啟服務,系統就會呼叫Service的onCreate()
image.png
通過onCreat()方法可以得出下邊的結論:

  • HandlerThread 一個執行緒類開啟一個工作執行緒
  • mServiceLooper為工作執行緒的Looper
  • ServiceHandler為工作執行緒的Handler
    首先Handler是主執行緒的Handler還是工作執行緒的Handler主要看它的Looper,而ServiceHandler的Looper為工作執行緒下的Looper,所以ServiceHandler屬於工作執行緒的Handler。判斷哪個執行緒的Handler,主要因為看handlerMessage()方法在哪個執行緒執行。
    其次為什麼說mServiceLooper為工作執行緒的Looper,
    image.png
    截圖是HandlerThread的run()方法。可以看到mServiceLooper是在run()裡面得到的,所以mServiceLooper為工作執行緒的Looper.。
    HandlerThread 一個執行緒類這個就不用說了。

HandlerThread

該類其實是幹嘛的呢?簡單來說,它就是幫我們建立一個工作執行緒的Looper,Looper的作用就是輪詢我們的訊息分發機制(這裡不細說,細說又是一篇了。。。)。詳細瞭解HandlerThread 可以看下面這篇文章
為什麼要用HandlerThread,怎麼用?

為什麼出現Handler,Looper這些訊息分發類別的類?

image.png
主要因為IntentService的onStart()方法中傳送了訊息,上面建立onCreat()時,構建了ServiceHandler物件。通過Handler訊息分發機制,處理抽象方法onHandleIntent();

使用IntentService,重寫onHandleIntent()方法

  • 第一,建立一個類繼承IntentService,實現onHandleIntent();
public class ParseIntentService extends IntentService {
public ParseIntentService() {
super("ParseIntentService");
}
/**
* 該方法在工作執行緒上呼叫
* */

@Override
protected void onHandleIntent(@Nullable Intent intent) {
//TODO 需要在服務做的事情
}
});
}
}
複製程式碼
  • 第二,建立Intent,呼叫startService()方法。
Intent serviceIntent = new Intent(this, ParseIntentService.class);
startService(serviceIntent);
複製程式碼

總結

  • onHandleIntent()方法是在工作執行緒上的;不用執行更新UI的工作
  • IntentService裡面已經有工作執行緒無需開啟新的工作執行緒。
    這裡想說一下:如果你在onHandleIntent()通過Retrofit呼叫介面,而又使用OkHttp的,建議使用Service不建議用IntentService。因為OkHttp已經幫我們建立了工作執行緒。這樣又用IntentService的工作執行緒又用IntentService實際上是一種記憶體消耗。
  • 這點給自己一個筆記通過這個IntentService最主要認識了在工作執行緒中的Handler;HandlerThread管理工作執行緒的Looper

相關文章