Android 總結:Message,MessageQueue,Looper,Handler 消息機制

一、關鍵概念

1. Message 消息對象

MessageQueue中的存放的對象,一個MessageQueue中可包含多個Message對象。
通過Message類裏的靜態方法obtain()可獲得Message實例對象:

這裏寫圖片描述

它的創建並不一定是直接創建一個新的實例:

  • 而是先從Message Pool(消息池)中看有沒有可用的Message實例,
    存在則直接取出返回這個實例。
  • 如果Message Pool中沒有可用的Message實例,
    才用給定的參數創建一個Message對象。
  • 調用removeMessages()時,將Message從Message Queue中刪除,同時放入到Message Pool中。

除了上面這種方式,也可以通過Handler對象的obtainMessage()獲取一個Message實例。

2. MessageQueue 消息隊列

存放消息的地方,每 一個線程最多隻可以擁有一個 MessageQueue數據結構。

  1. 通常使用一個Looper對象對該線程的MessageQueue進行管理。
  2. 創建一個線程的時候,一般並不會自動創建其MessageQueue:
    • 主線程創建時,會創建一個默認的Looper對象,而Looper對象的創建,將自動創建一個Message Queue。
    • 其他非主線程,不會自動創建Looper,要需要的時候,通過調用prepare()函數來實現。

3. Looper 消息管理者

每一個MessageQueue都不能脫離Looper而存在,Looper對象的創建是通過prepare()函數來實現的。

  /* This is a typical example of the implementation of a Looper thread, 
  * using the separation of prepare() and loop() 
  * to create an initial Handler to communicate with the Looper. 
  */
  class LooperThread extends Thread {
      public Handler mHandler;

      public void run() {
          Looper.prepare();

          mHandler = new Handler() {
              public void handleMessage(Message msg) {
                  // process incoming messages here
              }
          };

          Looper.loop();
      }
  }

每一個Looper對象和一個線程關聯,通過調用Looper.myLooper()可以獲得當前線程的Looper對象 。

這裏寫圖片描述

Looper從MessageQueue中取出Message然後,交由Handler的handleMessage()進行處理。
處理完成後,調用Message.recycle()將其放入Message Pool中。

4. Handler 消息處理者

Handler負責將需要傳遞的信息封裝成Message 。

  • 通過handler對象的sendMessage()將消息傳遞給Looper,繼而由Looper將Message放入MessageQueue中。
  • 當Looper對象看到MessageQueue中含有Message,就將其廣播出去。
    該handler對象收到該消息後,調用handler對象的handleMessage()方法進行處理。

二、線程之間的消息如何進行傳遞

1. 主線程給自己發送Message

public class MainActivity extends Activity {

    private Button btnTest;
    private TextView textView;

    private Handler handler;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        btnTest = (Button)this.findViewById(R.id.btn_01);
        textView = (TextView)this.findViewById(R.id.view_01);

        btnTest.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View arg0) {

                Looper looper = Looper.getMainLooper(); //主線程的Looper對象
                //這裏以主線程的Looper對象創建了handler,
                //所以,這個handler發送的Message會被傳遞給主線程的MessageQueue。
                handler = new MyHandler(looper);
                handler.removeMessages(0);

                //構建Message對象
                //第一個參數:是自己指定的message代號,方便在handler選擇性地接收
                //第二三個參數沒有什麼意義
                //第四個參數需要封裝的對象
                Message msg = handler.obtainMessage(1,1,1,"主線程發消息了");

                handler.sendMessage(msg); //發送消息

            }
        });
    }

    class MyHandler extends Handler{

        public MyHandler(Looper looper){
            super(looper);
        }

        public void handleMessage(Message msg){
            super.handleMessage(msg);
            textView.setText("我是主線程的Handler,收到了消息:"+(String)msg.obj);
        }
    }
}

2. 其他線程給主線程發送Message

public class MainActivity extends Activity {

    private Button btnTest;
    private TextView textView;

    private Handler handler;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        btnTest = (Button)this.findViewById(R.id.btn_01);
        textView = (TextView)this.findViewById(R.id.view_01);

        btnTest.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View arg0) {

                //可以看出這裏啓動了一個線程來操作消息的封裝和發送的工作
                //這樣原來主線程的發送就變成了其他線程的發送,簡單吧?呵呵
                new MyThread().start();    
            }
        });
    }

    class MyHandler extends Handler{
        public MyHandler(Looper looper){
            super(looper);
        }

        public void handleMessage(Message msg){
            super.handleMessage(msg);
            textView.setText("我是主線程的Handler,收到了消息:"+(String)msg.obj);
        }
    }

    //加了一個線程類
    class MyThread extends Thread{

        public void run(){
            Looper looper = Looper.getMainLooper(); //主線程的Looper對象
            //這裏以主線程的Looper對象創建了handler,
            //所以,這個handler發送的Message會被傳遞給主線程的MessageQueue。
            handler = new MyHandler(looper);

            //構建Message對象
            //第一個參數:是自己指定的message代號,方便在handler選擇性地接收
            //第二三個參數沒有什麼意義
            //第四個參數需要封裝的對象
            Message msg = handler.obtainMessage(1,1,1,"其他線程發消息了");

            handler.sendMessage(msg); //發送消息            
        }
    }
}

3. 主線程給其他線程發送Message

public class MainActivity extends Activity {

    private Button btnTest;
    private TextView textView;

    private Handler handler;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        btnTest = (Button)this.findViewById(R.id.btn_01);
        textView = (TextView)this.findViewById(R.id.view_01);


        //啓動線程
        new MyThread().start();    

        btnTest.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View arg0) {
                //這裏handler的實例化在線程中
                //線程啓動的時候就已經實例化了
                Message msg = handler.obtainMessage(1,1,1,"主線程發送的消息");
                handler.sendMessage(msg);
            }
        });
    }

    class MyHandler extends Handler{
        public MyHandler(Looper looper){
            super(looper);
        }

        public void handleMessage(Message msg){
            super.handleMessage(msg);
            textView.setText("我是主線程的Handler,收到了消息:"+(String)msg.obj);
        }
    }

    class MyThread extends Thread{
        public void run(){
            Looper.prepare(); //創建該線程的Looper對象,用於接收消息

            //注意了:這裏的handler是定義在主線程中的哦,呵呵,
            //前面看到直接使用了handler對象,是不是在找,在什麼地方實例化的呢?
            //現在看到了吧???呵呵,開始的時候實例化不了,因爲該線程的Looper對象
            //還不存在呢。現在可以實例化了
            //這裏Looper.myLooper()獲得的就是該線程的Looper對象了
            handler = new MyThreadHandler(Looper.myLooper());

            //這個方法,有疑惑嗎?
            //其實就是一個循環,循環從MessageQueue中取消息。
            //不經常去看看,你怎麼知道你有新消息呢???
            Looper.loop(); 

        }

        //定義線程類中的消息處理類
        class MyThreadHandler extends Handler{
            public ThreadHandler(Looper looper){
                super(looper);
            }

            public void handleMessage(Message msg){
                //這裏對該線程中的MessageQueue中的Message進行處理
                //這裏我們再返回給主線程一個消息
                handler = new MyHandler(Looper.getMainLooper());
                Message msg2 = handler.obtainMessage(1,1,1,"子線程收到:"+(String)msg.obj);
                handler.sendMessage(msg2);
            }
        }
    }
}

4. 其他線程給自己發送Message

public class MainActivity extends Activity {

    private Button btnTest;
    private TextView textView;

    private Handler handler;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        btnTest = (Button)this.findViewById(R.id.btn_01);
        textView = (TextView)this.findViewById(R.id.view_01);

        btnTest.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View arg0) {
                //啓動線程
                new MyThread().start();    
            }
        });
    }

    class MyHandler extends Handler{
        public MyHandler(Looper looper){
            super(looper);
        }

        public void handleMessage(Message msg){
            super.handleMessage(msg);
            textView.setText((String)msg.obj);
        }
    }    

    class MyThread extends Thread{
        public void run(){
            Looper.prepare(); //創建該線程的Looper對象
            //這裏Looper.myLooper()獲得的就是該線程的Looper對象了
            handler = new ThreadHandler(Looper.myLooper());
            Message msg = handler.obtainMessage(1,1,1,"我自己");
            handler.sendMessage(msg);

            Looper.loop(); 
        }

        //定義線程類中的消息處理類
        class ThreadHandler extends Handler{
            public ThreadHandler(Looper looper){
                super(looper);
            }

            public void handleMessage(Message msg){
                //這裏對該線程中的MessageQueue中的Message進行處理
                //這裏我們再返回給主線程一個消息
                //加入判斷看看是不是該線程自己發的信息
                if(msg.what == 1 && msg.obj.equals("我自己")){
                    handler = new MyHandler(Looper.getMainLooper());
                    Message msg2 = handler.obtainMessage(1,1,1,"稟告主線程:我收到了自己發給自己的Message");
                    handler.sendMessage(msg2);                
                }

            }
        }
    }
}

參考文章:
1. Android 中Message,MessageQueue,Looper,Handler詳解+實例

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章