生活随笔
收集整理的這篇文章主要介紹了
HandlerThread原理与应用
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
HandlerThread ?在理解了Handler的原理之后,我們知道在一個子線程中創建一個Handler不能缺少了Looper.prepare()和Looper.loop()兩個方法,具體的原因這里不再贅述,不熟悉原理的可以先看下另一篇文章Handler的原理解析. 本篇文章主要是講解HandlerThread的使用的。 ?首先HandlerThread是繼承于Thread類的,所以本質上HandlerThread就是一個線程,接下來就詳細的去看一看,這是怎樣的一個線程? ?首先,先看下它的構造函數:
public HandlerThread(String name) {super(name);mPriority = Process.THREAD_PRIORITY_DEFAULT;}
public HandlerThread(String name, int priority) {super(name);mPriority = priority;}
//很簡單,構造函數里只是設置了該Thread的名稱和優先級。
?既然是線程,那么最重要的當然是run方法來,看完了run方法,相信你也就明白HandlerThread的用途了!
@Overridepublic void run() {mTid = Process.myTid();Looper.prepare();synchronized (this) {mLooper = Looper.myLooper();notifyAll();}Process.setThreadPriority(mPriority);onLooperPrepared();Looper.loop();mTid = -1;}
?怎么樣,這是不是和我們之前在子線程中創建Handler一樣,首先是Looper.prepare(),接著是new Handler(), 最后是Looper.loop()。等等,這里并沒有創建Handler啊!別急,我們先一步一步地看看run方法再說為什么沒有創建Handler。
首先呢是調用了Looper.prepaer(),該方法為我們的線程創建了一個唯一的Looper和MessageQueue對象,具體的創建過程看另一篇文章Handler的原理解析 接下來有一個同步鎖的代碼塊,里面獲取到了創建好的Looper對象將其賦值給當前的mLooper,然后喚醒了鎖。注意這里有一個喚醒線程的操作,既然有喚醒鎖的操作,那么必定有有個地方使線程處于了阻塞的狀態,我們看下出現阻塞的地方。 public Looper getLooper() {if (!isAlive()) {return null;}// If the thread has been started, wait until the looper has been created.synchronized (this) {while (isAlive() && mLooper == null) {try {wait();} catch (InterruptedException e) {}}}return mLooper;}
?通過查找發現到一個getLooper()的方法,該方法返回了當前線程的mLooper對象,還記得Looper是在哪里進行賦值的嗎?在線程的run方法里,所以當線程啟動之后才能創建Looper并賦值給mLooper,這里的阻塞就是為了等待Looper的創建成功。同時該方法是用Public修飾的,說明該方法是提供外部調用的,Looper創建成功提供給外部使用。
接著我們回到run方法,Looper和MessageQueue已經創建成功了,接下來就是啟動Looper循環了(即Looper.loop()),別忘了只有Looper循環啟動后我們才能時刻觀察著MessageQueue,只要有Message了才能立馬將Message取出來進行分發處理。 在Looper.loop()之前還調用了一個onLooperPrepared()方法,這個方法是干嘛的呢? 看代碼可知,只是一個空方法,在使用HandlerThread時重寫該方法,方便在Looper輪詢消息之前做一些初始化的操作。 /*** Call back method that can be explicitly overridden if needed to execute some* setup before Looper loops.*/protected void onLooperPrepared() {}
?最后在對象銷毀前,調用下面的方法退出Looper循環
public boolean quit() {Looper looper = getLooper();if (looper != null) {looper.quit();return true;}return false;}
public boolean quitSafely() {Looper looper = getLooper();if (looper != null) {looper.quitSafely();return true;}return false;}
?quit方法實際是調用MessagQueue的removeAllMessagesLocked,移除所有延遲和非延遲的消息, ?quitSafely方法調用的是removeAllFutureMessagesLocked方法,該方法只清除延遲的消息,非延遲的消息 還是會進行分發處理。
?HandlerThread分析完啦,是不是有點蒙,自始至終都沒有出現Handler,HandlerThread要怎么用呢? ?下面我們就通過一個Demo來說明下HandlerThread是怎么用的?
private WorkHandler mHandler;private HandlerThread mHandlerThread;/*Handler存在一個構造函數,傳入一個Looper對象,Handler的handleMessage獲取的是Looper的MessageQueue中的Message因此,handleMessage的調用與Looper對象同屬于一個線程,這里我們在構造時傳入HandlerThread的Looper對象,handleMessage運行于HandlerThread線程(也就是一個子線程),所以Handler雖然是在住線程創建,但是它的handleMessage接收到消息是在HandlerThread線程,執行下代碼可以看到打印出如下log:D/HandlerThreadDemo: HandlerThread/Demo thread receiver the message from thread: mainlog也說明,message由主線程傳遞到了HandlerThread中。*/private class WorkHandler extends Handler {WorkHandler(Looper looper) {super(looper);}@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);String str = (String) msg.obj;Log.d(TAG, Thread.currentThread().getName() + " thread receiver the message from thread: " + msg.obj);}}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_handlerthread_demo);mHandlerThread = new HandlerThread("HandlerThread/Demo");mHandlerThread.start();mHandler = new WorkHandler(mHandlerThread.getLooper());Message msg = mHandler.obtainMessage();msg.obj = Thread.currentThread().getName();mHandler.sendMessage(msg);}
總結: HandlerThread繼承于Thread,本質上也是一個線程。 HandlerThread的run方法為本線程創建提供了Looper和MessageQueue對象,并開啟了Looper輪詢消息。 通過在需要發送Message的線程中創建Handler,為Handler提供來自HandlerThread的Looper對象。Handler則能 將消息發送到HandlerThread上去進行處理。 注意:這里Handler不僅僅能在主線程創建,在子線程同樣能夠創建,只需要將對應的Looper提供給Handler即可,所以HandlerThread 不僅適用于和主線程通信,同樣適用于和其他子線程通信。 最后需要注意的是在我們不需要這個looper線程的時候需要手動停止掉,即調用quit()或者quitSafely()。 最后補充一個在實際開發過程中使用到HandlerThread的場景: 存在多個耗時的任務需要放到開啟子線程依次去處理(串行處理任務),首先,HandlerThread是一個子線程, 適合處理耗時的任務,其次,Handler分發消息是通過MessageQueue頂部的Message不斷的通過Message的next依次取出 Message,符合任務的按順序串行處理的要求,所以使用HandlerThread就能完美的解決此需求。
總結
以上是生活随笔 為你收集整理的HandlerThread原理与应用 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。