Handler

在Handler 異步實現時,涉及到 Handler, Looper, Message,Thread四個對象java

Message:消息,其中包含了消息ID,消息處理對象以及處理的數據等,由MessageQueue統一列隊,終由Handler處理。多線程

Handler:處理者,負責Message的發送及處理。使用Handler時,須要實現handleMessage(Message msg)方法來對特定的Message進行處理,例如更新UI等。併發

MessageQueue:消息隊列,用來存放Handler發送過來的消息,並按照FIFO規則執行。固然,存放Message並不是實際意義的保存,而是將Message以鏈表的方式串聯起來的,等待Looper的抽取。異步

Looper:消息泵,不斷地從MessageQueue中抽取Message執行。所以,一個MessageQueue須要一個Looperide

Thread:線程,負責調度整個消息循環,即消息循環的執行場所。oop

 

實現異步的流程:post

主線程啓動子線程 -> 子線程運行並生成Message而後發送到MessageQueue -> Looper獲取Message並傳遞給Handler ->Handler逐個獲取Looper中的Message並進行UI更新等操做。ui

線程在空閒(原子操做之間的間隙)時啓動Looper的loop(),裏面是for(;;),直到沒有message纔會結束。spa

因此HandleMessage不能有太耗時操做,message過多也會對UI刷新有影響。線程

 

Framework在Activity,Service等系統組件的主線程(UI線程---這個名稱很差,好比Service就沒UI)中會默認建Looper。

一個線程對應一個Looper,一個Looper對應一個MessageQueue。

每一個線程最多隻有一個Looper對象,它的本質是一個ThreadLocal,而ThreadLocal是在JDK1.2中引入的,它爲解決多線程程序的併發問題提供了一種新思路。

子線程建立Handler要傳入new Looper,若是本身定義子線程的Looper,方法以下:

    public static prepare();
    public static myLooper();
    public static loop();
    public void quit();
使用方法以下:
1. 在每一個線程的run()方法中的最開始調用Looper.prepare(),這是爲線程初始化消息隊列。
2. 以後調用Looper.myLooper()獲取此Looper對象的引用。這不是必須的,可是若是你須要保存Looper對象的話,必定要在prepare()以後,不然調用在此對象上的方法不必定有效果,如looper.quit()就不會退出。
3. 在run()方法中添加Handler來處理消息
4. 添加Looper.loop()調用,這是讓線程的消息隊列開始運行,能夠接收消息了。
5. 在想要退出消息循環時,調用Looper.quit()注意,這個方法是要在對象上面調用,很明顯,用對象的意思就是要退出具體哪一個Looper。若是run()中無其餘操做,線程也將終止運行。

 

另一種經常使用方法,簡便:

mHandler = new Handler();
        mRunnable = new Runnable() {

            @Override
            public void run() {
                mTextView.setText("haha");
            }
        };
        mButton.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                new Thread() {
                    public void run() {
                        mHandler.post(mRunnable);
                    }
                }.start();
            }
        });
    }

使用Handler的post()方法就顯得UI的更新處理很是簡單:在一個Runnable對象中更新UI,而後在另外一個線程中經過Handler的post()執行該更新動做。值得注意的是,咱們就算不用新開一個新線程照樣能夠更新UI,由於UI的更新線程就是Handler的建立線程---主線程。

表面上Handler彷佛能夠發送兩種消息:Runnable對象和Message對象,實際上Runnable對象會被封裝成Message對象。

 

總結:

·      Handler的處理過程運行在建立Handler的線程裏

·      一個Looper對應一個MessageQueue

·      一個線程對應一個Looper

·      一個Looper能夠對應多個Handler

·      不肯定當前線程時,更新UI時儘可能調用post方法

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息