Handler和HandlerThread總結

一般我們使用Hanlder是在子線程和UI線程(主線程)之間傳遞消息,當Hanlder在UI線程中new出來時候,如果沒有顯示指定looper的話,會自動綁定當前所在線程即UI線程的Looper,looper管理了一個MessageQueue。其他子線程就可以通過持有該Hanlder的引用,傳遞消息message,message被放到MessageQueue里面,并被相應handler所綁定線程的looper取出來,在handler的handleMessage()方法里執(zhí)行相應的處理。handleMessage()所執(zhí)行的線程就是handler綁定的looper所在的線程。

UI線程創(chuàng)建時候會自動初始化looper的相關操作,而為子線程創(chuàng)建對應handler則必須手動執(zhí)行這些步驟。如下:

Handler mHandler;
private void createManualThreadWithHandler() {
  new Thread() {
      @Override
        public void run() {
            super.run();
            Looper.prepare();//生成looper
            mHandler = new Handler(Looper.myLooper()) {//顯式持有子線程的looper
                @Override
                public void handleMessage(Message msg) {
                    //實際的耗時處理任務,在子線程中運行
                };
            Looper.loop();//不斷查詢是否有消息進來,此處是死循環(huán)
        }
    }.start();
}

子線程收到消息后實際任務處理在handleMessage中執(zhí)行。

HandlerThread實際就是一個Thread,為了方便我們?yōu)槠鋭?chuàng)建handler,就在run方法里做了Looper的相應初始化操作,源碼如下:

//調用 start() 后就會執(zhí)行的 run()
@Override
public void run() {
    mTid = Process.myTid();
    Looper.prepare();            //幫我們創(chuàng)建了 Looepr
    synchronized (this) {
        mLooper = Looper.myLooper();
        notifyAll();    //Looper 已經創(chuàng)建,喚醒阻塞在獲取 Looper 的線程
    }
    Process.setThreadPriority(mPriority);
    onLooperPrepared();    
    Looper.loop();        //開始循環(huán)
    mTid = -1;
}

對HandlerThread我們就可以這樣為其創(chuàng)建handler,省去了looper的準備工作:

HandlerThread handlerThread = new HandlerThread("name");
handlerThread.start();
Handler threadHanler = new Handler(handlerThread.getLooper()) {
    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        //do something
        //此處代碼實際運行在子線程:handlerThread
    }
};

當然,也可以通過在重新的onLooperPrepared()方法來創(chuàng)建handler:

class MyHandlerThread extends HandlerThread {
    Handler mHandlerThreadHandler;
    public MyHandlerThread(String name) {
        super(name);
    }

    @Override
    protected void onLooperPrepared() {
        super.onLooperPrepared();
        mHandlerThreadHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                SystemClock.sleep(2000);//模擬耗時操作

                Toast.makeText(MainActivity.this, "handlerThread:" + msg.obj, Toast.LENGTH_SHORT).show();
                super.handleMessage(msg);
            }
        };
    }
}

參考:

http://blog.csdn.net/u011240877/article/details/72905631

http://droidyue.com/blog/2015/11/08/make-use-of-handlerthread/index.html

http://blog.csdn.net/lmj623565791/article/details/47079737

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容