標籤:android message messagequeue handler looper
一、幾個關鍵概念
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
packagetest.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 extendsActivity { privateButton btnTest; privateTextView textView; privateHandler handler; @Override publicvoid 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(newView.OnClickListener() { @Override publicvoid onClick(View arg0) { //啟動線程 newMyThread().start(); } }); } classMyHandler extendsHandler{ publicMyHandler(Looper looper){ super(looper); } publicvoid handleMessage(Message msg){ super.handleMessage(msg); textView.setText((String)msg.obj); } } classMyThread extendsThread{ publicvoid run(){ Looper.prepare();//建立該線程的Looper對象 //這裡Looper.myLooper()獲得的就是該線程的Looper對象了 handler =new ThreadHandler(Looper.myLooper()); Message msg = handler.obtainMessage(1,1,1,"我自己"); handler.sendMessage(msg); Looper.loop(); } //定義線程類中的訊息處理類 classThreadHandler extendsHandler{ publicThreadHandler(Looper looper){ super(looper); } publicvoid 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); } } } }}
Android之Message,MessageQueue,Looper,Handler詳解(帶樣本)