在Android開發中,咱們一般會將一些耗時操做放到一個Service中執行,可是普通的Service默認是運行在主線程中的,咱們沒法直接在主線程中執行耗時操做,這就須要咱們本身在Service中維護一個子線程,相對來講比較麻煩。爲了解決這個問題,Google爲咱們提供了一個IntentService,與普通的Service相比,IntentService會自動建立一個子線程用來執行任務,而且當任務執行完成後,IntentService會自動關閉服務,使用起來很是方便。java
##IntentService的使用方法 IntentService的使用方法很是簡單,舉一個簡單的例子:markdown
public class IntentServiceExample extends IntentService {
/** * 在構造方法中調用了父類的構造方法IntentService(String name) * 參數name用來對工做線程進行命名,方便進行調試 */
public IntentServiceExample() {
super("IntentServiceExample");
}
/** * 重寫父類的onHandleIntent方法,在該方法中實現本身所需的業務邏輯 */
@Override
protected void onHandleIntent(@Nullable Intent intent) {
try {
Log.e("Test", Thread.currentThread().getName() + ":task start");
Thread.sleep(3000);//讓線程休眠3秒,用來模擬耗時任務
Log.e("Test", Thread.currentThread().getName() + ":task finish");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
複製代碼
咱們首先要新建一個類來繼承自IntentService,而後重寫onHandleIntent方法,並在該方法中實現咱們所需的業務邏輯,而後咱們只須要像啓動一個普通Service那樣來啓動IntentService便可:ide
Intent intent = new Intent(MainActivity.this,IntentServiceExample.class);
startService(intent);
複製代碼
經過log日誌能夠看到,onHandleIntent方法是運行在一個子線程中的:oop
E/Test: IntentService[IntentServiceExample]:task start
E/Test: IntentService[IntentServiceExample]:task finish
複製代碼
須要注意的是使用IntentService也須要在AndroidManifest文件中進行註冊,不然IntentService將沒法正常工做。學習
##HandlerThread工做原理解析ui
如今咱們已經掌握了IntentService的基本使用方法了,可是在分析IntentService的工做原理以前,咱們首先來看一個名爲HandlerThread的類,由於HandlerThread是IntentService中很是重要的一個對象,所以瞭解HandlerThread的原理有助於咱們去學習IntentService的工做機制。this
從HandlerThread的名字咱們就能看出,HandlerThread應該是繼承自Thread類,所以它自己也是一個Thread。其中run方法是HandlerThread中一個比較重要的方法,咱們來看一下run方法的源碼:spa
public class HandlerThread extends Thread {
Looper mLooper;
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare(); //調用Looper的prepare方法
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop(); //調用Looper的loop方法
mTid = -1;
}
...
}
複製代碼
能夠看到,在HandlerThread的run方法中調用了Looper的prepare方法和loop方法。由此咱們能夠得知,HandlerThread與普通Thread的最大區別就在於,HandlerThread默認開啓了該線程中的消息循環系統。(關於Android中的消息系統,不瞭解的同窗能夠去看一下個人另外一篇博客Android中的消息系統————Handler,MessageQueue與Looper)線程
HandlerThread還提供了一個getLooper方法,用來獲取該線程所對應的Looper:調試
public Looper getLooper() {
if (!isAlive()) {
return null;
}
// 若是該線程已經被啓動,可是還沒有開始消息循環,則等待直到消息循環系統啓動完成
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
複製代碼
這樣咱們即可以經過HandlerThread來很方便的來處理一些業務邏輯,IntentService即是一個運用了HandlerThread的典型例子,接下來咱們便一塊兒來分析一下IntentService的工做原理。
##IntentService的工做原理
在瞭解了HandlerThread以後,咱們終於能夠來分析一下IntentService的工做原理了。先列出IntentService的源碼:
public abstract class IntentService extends Service {
private volatile Looper mServiceLooper;
private volatile ServiceHandler mServiceHandler;
...//省略部分代碼
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);
}
}
@Override
public void onCreate() {
super.onCreate();
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
@Override
public void onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
@Override
public void onDestroy() {
mServiceLooper.quit();
}
@WorkerThread
protected abstract void onHandleIntent(@Nullable Intent intent);
}
複製代碼
能夠看到IntentService繼承自Service,那麼IntentService天然也擁有Service的全部生命週期方法。咱們首先來看onCreate方法:
@Override
public void onCreate() {
super.onCreate();
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
複製代碼
能夠看到在onCreate方法中首先建立並開啓了一個HandlerThread對象,前面咱們已經分析過了HandlerThread的工做原理,能夠得知這個HandlerThread線程會默認開啓它的消息系統。以後又經過getLooper方法來獲取了這個HandlerThread中的Looper對象,並經過這個Looper對象初始化了一個Handler,即mServiceHandler,所以經過mServiceHandler發送的message最終都會在這個HandlerThread線程中執行。(若是有同窗對Android中的Handler與消息系統還不瞭解,建議先去看一下個人另外一篇博客Android中的消息系統————Handler,MessageQueue與Looper)。
而後咱們再來看一下IntentService的onStart方法:
@Override
public void onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
複製代碼
onStart方法的代碼很簡單,就是經過以前在onCreate中初始化的mServiceHandler來發送了一條消息。咱們來看一下mServiceHandler的代碼:
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);
}
}
複製代碼
能夠看到在ServiceHandler的handleMessage方法中直接調用了onHandleIntent方法,因爲mServiceHandler是經過HandlerThread線程的Looper來建立的,所以onHandleIntent方法將在HandlerThread中被執行。
在執行完onHandleIntent方法後,IntentService又調用了stopSelf方法來結束了本服務,所以IntentService是一種「用完即走」的服務,無需咱們手動去結束服務。
須要注意的是,IntentService的onBind方法默認返回爲null,所以咱們不建議使用bindService的方法來綁定IntentService:
@Override
@Nullable
public IBinder onBind(Intent intent) {
return null;
}
複製代碼
在Android8.0以後,谷歌增強了對後臺服務的限制,當應用處於後臺時,將沒法經過startService開啓後臺服務,IntentService也受此限制的影響,Google推薦使用JobIntentService來替代IntentService。