相信你們在 Android 開發中也用到過 IntentService 和 HandlerThread 這兩個類,那麼咱們今天就來分析一下這兩個類。java
IntentService 是 Service 的一個子類,它的內部有一個 Handler 和 HandlerThread。因此 IntentService 與 Service 最大的不一樣就是 IntentService 在後臺開啓了一個子線程,而 Service 並無,它仍是在 UI 線程裏。android
IntentService 經過 Handler 和 HandlerThread 來開啓一個線程,那麼咱們先來看一看 HandlerThread 的源碼。ide
只貼 HandlerThread 的部分代碼:oop
package android.os;
public class HandlerThread extends Thread {
int mPriority;
int mTid = -1;
Looper mLooper;
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}
public HandlerThread(String name, int priority) {
super(name);
mPriority = priority;
}
/** * Call back method that can be explicitly overridden if needed to execute some * setup before Looper loops. */
protected void onLooperPrepared() {
}
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare(); //在本線程中建立一個 Looper。
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority); //設置線程優先級
onLooperPrepared();
Looper.loop(); //looper 循環,開始從 MessageQueue 獲取 messages
mTid = -1;
}
}複製代碼
從代碼裏能夠看到,HandlerThread 繼承於 Thread ,並重寫了 run() 方法。
在 run() 方法裏,經過 Looper.prepare() 建立當前線程的 Looper。隨後設置當前線程的優先級,並調用 Looper.loop() 使當前線程的 Looper 開始循環,開始從 Looper 自帶的 MessageQueue 中獲取消息。因此,HandlerThread 就是一個自帶消息隊列的 Thread。ui
使用 HandlerThread 的時候要配合 Handler 一塊兒使用,使用例子以下:this
HandlerThread handlerThread = new HandlerThread("Juhezi");
handlerThread.start(); //開啓線程,同時也開啓了消息循環
Looper looper = handlerThread.getLooper(); //獲取 HandlerThread 中的 Looper
Handler handler = new Handler(looper); //經過 Looper 初始化 Handler複製代碼
這時,經過 handler 發送的消息,都會存儲在 handlerThread 中的消息隊列裏。spa
若是想讓 handlerThread 退出,只須要執行 handlerThread 的 quit()\quitSafely() 方法,這裏實際上是調用了 looper 的 quit()\quitSafely() 方法。線程
接下來就開始正式分析 IntentService。code
IntentService 中有一個內部類 ServiceHandler,它繼承了 Handler,它的構造方法須要一個 Looper。IntentService 就是這個 ServiceHandler 的實例來進行發送消息,處理消息的。
ServiceHandler 重載的 handleMessage() 中就是對消息的處理方式,從代碼可見,它首先執行一個 onHandleIntent() 方法,而後執行 stopSelf 結束 Service(本身)。那個 onHandlerMessage() 是一個抽象方法。在這裏能夠得出一個結論,繼承
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); //結束 Service
}
}複製代碼
而後來看 onCreate() 方法,仔細一看,不就是和咱們上面講過的 HandlerThread 一個套路嘛:建立一個 HandlerThread,調用其 start 方法,而後獲取根據 HandlerThread 的 Looper 建立一個 Handler,不過這裏是它的子類:ServiceHandler。
@Override
public void onCreate() {
super.onCreate();
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}複製代碼
接着來看 onStart() 方法,很明顯,就是把傳入的 Intent 和 startId 包裝成 message,經過 mServiceHandler 發送出去,這個時候,你就能夠在重載的 onHandlerMessage 中處理這個信息。
注意:這個重載的 onHandlerMessage 是在工做線程中被調用的,因此你能夠在這裏執行一些耗時任務。
@Override
public void onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}複製代碼
經過源碼,咱們還知道,不建議經過 bindService() 的 方式啓動 IntentService,建議使用 startService() 的方式。
最後,咱們看一下這個 IntentService 的具體使用方法:
public class TestService extends IntentService {
private static final String ACTION_FOO = "com.juhezi.test.action.FOO";
private static final String ACTION_BAZ = "com.juhezi.test.action.BAZ";
private static final String EXTRA_PARAM1 = "com.juhezi.test.extra.PARAM1";
private static final String EXTRA_PARAM2 = "com.juhezi.test.extra.PARAM2";
public static final String TAG = "TestService";
public TestService() {
super("TestService");
}
public static void startActionFoo(Context context, String param1, String param2) {
Intent intent = new Intent(context, TestService.class);
intent.setAction(ACTION_FOO);
intent.putExtra(EXTRA_PARAM1, param1);
intent.putExtra(EXTRA_PARAM2, param2);
context.startService(intent);
}
public static void startActionBaz(Context context, String param1, String param2) {
Intent intent = new Intent(context, TestService.class);
intent.setAction(ACTION_BAZ);
intent.putExtra(EXTRA_PARAM1, param1);
intent.putExtra(EXTRA_PARAM2, param2);
context.startService(intent);
}
@Override
protected void onHandleIntent(Intent intent) {
if (intent != null) {
final String action = intent.getAction();
if (ACTION_FOO.equals(action)) {
final String param1 = intent.getStringExtra(EXTRA_PARAM1);
final String param2 = intent.getStringExtra(EXTRA_PARAM2);
handleActionFoo(param1, param2);
} else if (ACTION_BAZ.equals(action)) {
final String param1 = intent.getStringExtra(EXTRA_PARAM1);
final String param2 = intent.getStringExtra(EXTRA_PARAM2);
handleActionBaz(param1, param2);
}
}
}
/** * Handle action Foo in the provided background thread with the provided * parameters. */
private void handleActionFoo(String param1, String param2) {
Log.i(TAG, "handleActionFoo: " + param1 + " " + param2);
}
/** * Handle action Baz in the provided background thread with the provided * parameters. */
private void handleActionBaz(String param1, String param2) {
Log.i(TAG, "handleActionBaz: " + param1 + " " + param2);
}
}複製代碼
感謝閱讀。