HandlerThread+IntentService

Android 線程簡單分析(一) Android 併發之synchronized鎖住的是代碼仍是對象(二) Android 併發之CountDownLatch、CyclicBarrier的簡單應用(三) Android 併發HashMap和ConcurrentHashMap的簡單應用(四)(待發布) Android 併發之Lock、ReadWriteLock和Condition的簡單應用(五) Android 併發之CAS(原子操做)簡單介紹(六) Android 併發Kotlin協程的重要性(七)(待發布) Android 併發之AsyncTask原理分析(八) Android 併發之Handler、Looper、MessageQueue和ThreadLocal消息機制原理分析(九) Android 併發之HandlerThread和IntentService原理分析(十)併發

首先HandlerThread是一個線程而不是Handler,爲了講解HandlerThread,因此不得不提Looper輪訓器,若是看過Handler源碼的同窗應該很清楚,Handler 發送消息到Looper的MessageQueue中,而後Looper的loop方中不斷輪訓的從MessageQueue中取出消息,並分發給Handler處理,即loop方法在那個線程調用,那麼消息的處理就在那個險種中:ide

for (;;) {
        Message msg = queue.next(); // might block
        if (msg == null) {
        //沒有消息代表消息隊列正在退出。
            return;
        }
        //消息分發,Message的target持有指定Handler的的引用,分發給指定的Handler處理消息
         msg.target.dispatchMessage(msg);
        //回收message並放入消息池中
        msg.recycleUnchecked();
    }
複製代碼

明白的Looper的做用以後,接下看看HandlerThread,應該很好理解,HandlerThread繼承Thread,不是一個Handler,其封裝了Handler、Thread,官方是這樣解析這個類,一個很方便的用於啓動一個具備Looper的新線程。 而後能夠使用這個Looper建立Handler類。必需要先調用start方法:oop

@Override
public void run() {
    mTid = Process.myTid();
    Looper.prepare();
    synchronized (this) {
        mLooper = Looper.myLooper();
        notifyAll();//喚醒等待的線程
    }
    Process.setThreadPriority(mPriority);
    onLooperPrepared();
    Looper.loop();
    mTid = -1;
}

 public Looper getLooper() {
    if (!isAlive()) {
        return null;
    }
    
    // 若是線程已經啓動,一直等待知道Looper被建立。
    synchronized (this) {
        while (isAlive() && mLooper == null) {
            try {
                wait();
            } catch (InterruptedException e) {
            }
        }
    }
    return mLooper;
}
複製代碼

這兩個就是主要的代碼,因此我前面說了,必需要調用start方法啓動線程,在run方法中建立Looper,這樣咱們若是須要在子線程中處理消息,能夠使用這個Looper來建立Handler, getLooper()方法就是拿到HandlerThread的建立Looper;ui

###IntentService:this

講完HandlerThread,必然就是IntentService了,其也是一個Service,只是其在工做線程中運行,可是他是每次提交任務,也是在同一個線程中串行執行,IntentService其分裝了HandlerThread,並使用HandlerThread的Looper做爲處理消息的線程:spa

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

在Oncreate生命週期方法中建立了HandlerThread ,並使用期Looper建立ServiceHandler,service的聲明週期是:首次建立會調用oncreate方法,以後都會調用onStartCommand->onStart因此:線程

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

每次啓動IntentService都會調用mServiceHandler.sendMessage(msg);發消息,並在handler處理消息,因此這些消息都是串行執行的:code

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);
    }
}
複製代碼

當onHandleIntent方法執行結束以後,IntentService會嘗試經過stopSelf(int startId)來嘗試中止服務。之因此不用stopSelf()來中止服務,是由於stopSelf()會馬上中止服務,而stopSelf(int startId)則會等待全部的消息都處理完畢纔回終止服務。通常來講,stopSelf(int startId)在嘗試中止服務以前會判斷最近啓動服務的次數是否和startId相等,若是相等則馬上中止服務。協程

若是服務中止,會把全部的消息清除對象

@Override
public void onDestroy() {
    mServiceLooper.quit();
}
複製代碼

爲何不建議經過 bindService() 啓動 IntentService?

  • 手動調用bindService()後,自動調用內部方法:onCreate()、onBind()
  • 手動調用startService()後,自動調用內部方法:onCreate()、onStartCommand、onStart,由於bindService後沒有回調onStart,因此沒有發送消息,就不會執行 onHandleIntent()方法。
  • 時使用startService()啓動服務、BindService()綁定服務的生命週期: onCreate()、onStartCommand、onStart、onBind()

固然若是你要是同時使用startService()啓動服務、BindService()綁定服務的生命週期,那我就無話可說了,我是以爲可行,具體需求我沒用過,若是哪位同窗有這種需求,能夠討論哦。

本站公眾號
   歡迎關注本站公眾號,獲取更多信息