Android 中Message,MessageQueue,Looper,Handler詳解+實例

一、幾個關鍵概念

1、MessageQueue:是一種數據結構,見名知義,就是一個消息隊列,存放消息的地方。每一個線程最多只可以擁有一個MessageQueue數據結構。
創建一個線程的時候,並不會自動創建其MessageQueue。通常使用一個Looper對象對該線程的MessageQueue進行管理。主線程創建時,會創建一
個默認的Looper對象,而Looper對象的創建,將自動創建一個Message Queue。其他非主線程,不會自動創建Looper,要需要的時候,通過調
用prepare函數來實現。

2、Message:消息對象,Message Queue中的存放的對象。一個Message Queue中包含多個Message。
Message實例對象的取得,通常使用Message類裏的靜態方法obtain(),該方法有多個重載版本可供選擇;它的創建並不一定是直接創建一個新的實例,
而是先從Message Pool(消息池)中看有沒有可用的Message實例,存在則直接取出返回這個實例。如果Message Pool中沒有可用的Message實例,
則才用給定的參數創建一個Message對象。調用removeMessages()時,將Message從Message Queue中刪除,同時放入到Message Pool中。除了上面這
種方式,也可以通過Handler對象的obtainMessage()獲取一個Message實例。

3、Looper:
是MessageQueue的管理者。每一個MessageQueue都不能脫離Looper而存在,Looper對象的創建是通過prepare函數來實現的。同時每一個Looper對象
和一個線程關聯。通過調用Looper.myLooper()可以獲得當前線程的Looper對象
創建一個Looper對象時,會同時創建一個MessageQueue對象。除了主線程有默認的Looper,其他線程默認是沒有MessageQueue對象的,所以,不能
接受Message。如需要接受,自己定義一個Looper對象(通過prepare函數),這樣該線程就有了自己的Looper對象和MessageQueue數據結構了。
Looper從MessageQueue中取出Message然後,交由Handler的handleMessage進行處理。處理完成後,調用Message.recycle()將其放入Message Pool中。

4、Handler:
消息的處理者,handler負責將需要傳遞的信息封裝成Message,通過調用handler對象的obtainMessage()來實現;
將消息傳遞給Looper,這是通過handler對象的sendMessage()來實現的。繼而由Looper將Message放入MessageQueue中。
當Looper對象看到MessageQueue中含有Message,就將其廣播出去。該handler對象收到該消息後,調用相應的handler對象的handleMessage()方法
對其進行處理。


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

1、主線程給自己發送Message

package test.message; 
import android.app.Activity; 
import android.os.Bundle; 
import android.os.Handler; 
import android.os.Looper; 
import android.os.Message; 
import android.view.View; 
import android.widget.Button; 
import android.widget.TextView; 
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

package test.message; 
import android.app.Activity; 
import android.os.Bundle; 
import android.os.Handler; 
import android.os.Looper; 
import android.os.Message; 
import android.view.View; 
import android.widget.Button; 
import android.widget.TextView; 
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

package test.message; 
import android.app.Activity; 
import android.os.Bundle; 
import android.os.Handler; 
import android.os.Looper; 
import android.os.Message; 
import android.view.View; 
import android.widget.Button; 
import android.widget.TextView; 
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 ThreadHandler(Looper.myLooper()); 
            //這個方法,有疑惑嗎? 
            //其實就是一個循環,循環從MessageQueue中取消息。 
            //不經常去看看,你怎麼知道你有新消息呢??? 
            Looper.loop();  
        } 
        //定義線程類中的消息處理類 
        class ThreadHandler 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

package test.message; 
import android.app.Activity; 
import android.os.Bundle; 
import android.os.Handler; 
import android.os.Looper; 
import android.os.Message; 
import android.view.View; 
import android.widget.Button; 
import android.widget.TextView; 
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);                 
                } 
            } 
        } 
    } 
} 

附註: 上面四個例子的佈局文件是同一個文件main.xml

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:rientation="vertical" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    > 
<TextView  android:id="@+id/view_01" 
    android:layout_width="fill_parent"  
    android:layout_height="wrap_content"  
    android:text="@string/hello" 
    /> 
<Button android:id="@+id/btn_01"  
    android:layout_width="fill_parent"  
    android:layout_height="wrap_content"  
    android:text="測試消息" /> 
</LinearLayout>

另附上原文鏈接

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