1.??Message Queue的角色
l???在你的Android程序里,新创建一个线程,或称线程(Thread)时,并不会自动建立其Message Loop。
l???Android里并没有Global的Message Queue数据结构,例如,不同APK里的对象不能透过Massage Queue来交换消息(Message)。
l???一个线程可以创建一个Looper对象,由它来管理此线程里的Message Queue。
l???你可以创建Handler对象来与Looper沟通,以便push新消息到Message Queue里或者接收Looper(从Message Queue取出)所送来的消息。
l???线程A的Handler对象引用可以传递给别的线程,让别的线程B或C等能发送消息来给线程A(存于A的Message Queue里)。
l???线程A的Message Queue里的消息,只有线程A所属的对象可以处理之。
l???使用Looper.myLooper可以取得目前线程的Looper对象引用。
l???使用mHandler =?new?EventHandler(Looper.myLooper());可创建用来处理目前线程的Handler对象;其中,EventHandler是Handler的子类别。
l???使用mHandler =?new?EventHandler(Looper.getMainLooper());可创建用来处理main线程的Handler对象;其中,EventHandler是Handler的子类别。
?
2.?范例之一:Looper类之角色
Looper类别用来管理特定线程内对象之间的消息交换(Message Exchange)。你的应用程序可以创建许多个线程,或称线程(Thread)。而一个线程可以实例化许多个对象,这些对象之间常常需要互相交换消息。如果有这种需要,您可以替线程创建一个Looper类对象,来处理信息交换的管理工作。Looper对象会建立一个MessageQueue数据结构来存放各对象传来的消息(包括UI事件或System事件等)。如下图:
?
?
??每一个线程(Thread,或称「线程」)里可含有一个Looper对象以及一个MessageQueue数据结构。在你的应用程序里,可以定义Handler的子类别来接收Looper所送出的消息。
?
//----- Looper_01范例?-----
package?com.misoo.kx04;
import?android.app.Activity;
import?android.graphics.Color;
import?android.os.Bundle;
import?android.os.Handler;
import?android.os.Looper;
import?android.os.Message;
import?android.view.View;
import?android.view.View.OnClickListener;
import?android.widget.Button;
import?android.widget.LinearLayout;
import?android.widget.TextView;
?
public?class?ac01?extends?Activity?implements?OnClickListener {
????private?final?int?WC?= LinearLayout.LayoutParams.WRAP_CONTENT;
????private?final?int?FP?= LinearLayout.LayoutParams.FILL_PARENT;
????public?TextView?tv;
????private?EventHandler?mHandler;
????private?Button?btn,?btn2,?btn3;
???
????public?void?onCreate(Bundle icicle) {
????????super.onCreate(icicle);
????????LinearLayout layout =?new?LinearLayout(this);
????????layout.setOrientation(LinearLayout.VERTICAL);
??????????????????????????????
????????btn?=?new?Button(this);
????????btn.setId(101);
????????btn.setBackgroundResource(R.drawable.heart);
????????btn.setText("test looper");
????????btn.setOnClickListener(this);
????????LinearLayout.LayoutParams param =new?LinearLayout.LayoutParams(100,50);
????????param.topMargin?= 10;
????????layout.addView(btn, param);
???????????????
????????btn2?=?new?Button(this);
????????btn2.setId(102);
????????btn2.setBackgroundResource(R.drawable.ok_blue);
????????btn2.setText("exit");
????????btn2.setOnClickListener(this);
????????layout.addView(btn2, param);
???????????????
????????tv?=?new?TextView(this);
????????tv.setTextColor(Color.WHITE);
????????tv.setText("");
????????LinearLayout.LayoutParams param2 = new?LinearLayout.LayoutParams(FP,?WC);
????????param2.topMargin?= 10;
????????layout.addView(tv, param2);
????????setContentView(layout);?????
????}
????????public?void?onClick(View v) {
???????????switch(v.getId()){
??????????????case?101: Looper looper;
??????????????????? looper = Looper.myLooper();
??????????????????? mHandler?=?new?EventHandler(looper);
??????????????????? mHandler.removeMessages(0);
????????????????????//?清除整个MessageQueue里的事件,确保不会通知到别人
????????????????????String obj =?"This my message!";
????????????????????Message m =?mHandler.obtainMessage(1, 1, 1, obj);
????????????????????//?组装成一个Message物件
????????????????????mHandler.sendMessage(m);
????????????????????//?将Message物件送入MessageQueue里
????????????????????? break;
???????????????case?102:
??????????????????finish();
??????????????????break;
??????????}
???}
//------------------------------------------------------?????????????
class?EventHandler?extends?Handler{
????public?EventHandler(Looper looper) {
???????super(looper);
????}
????@Override
????public?void?handleMessage(Message msg) {
????????tv.setText((String)msg.obj);
????}
??}
}
//-------------------------------------------------------
说明:
??程序启动时,当前线程(即主线程, main thread)已创建了一个Looper对象,并且有了一个MessageQueue数据结构。
??指令:looper = Looper.myLooper();调用Looper类的静态myLooper()函数,以取得目前线程里的Looper对象引用。
指令:mHandler?=?new?EventHandler(looper);创建一个EventHandler对象来与Looper沟通。Activity等对象可以通过EventHandler对象来将消息传给Looper,然后放入MessageQueue里;EventHandler对象也扮演Listener的角色,可接收Looper对象所送来的消息。如下图:
?
?
指令:Message m =?mHandler.obtainMessage(1, 1, 1, obj);? 先创建一个Message对象,并将数据存入次对象里。
指令:mHandler.sendMessage(m);? 通过mHandler对象而将消息m传给Looper,然后放入MessageQueue里。
此时Looper对象看到MessageQueue里有消息m,就将它广播出去, mHandler对象接到此消息时,会调用其handleMessage()函数来处理之,于是输出"This my message!"于画面上,如下:
?
?
?
3.?范例之二:由别的线程发送到主线程的Message Queue
?
//----- Looper_02范例?-----
package?com.misoo.kx04;
import?android.app.Activity;
import?android.graphics.Color;
import?android.os.Bundle;
import?android.os.Handler;
import?android.os.Looper;
import?android.os.Message;
import?android.view.View;
import?android.view.View.OnClickListener;
import?android.widget.Button;
import?android.widget.LinearLayout;
import?android.widget.TextView;
?
public?class?ac01?extends?Activity?implements?OnClickListener {
???????????private?final?int?WC?= LinearLayout.LayoutParams.WRAP_CONTENT;
???????????private?final?int?FP?= LinearLayout.LayoutParams.FILL_PARENT;
???????????public?TextView?tv;
????private?myThread?t;
????private?Button?btn,?btn2,?btn3;
???
????public?void?onCreate(Bundle icicle) {
????????????????//文章长度有限,代码请参考上例
???????????????}
??????????????public?void?onClick(View v) {
?????????????????????switch(v.getId()){
?????????????????????case?101:
???????????????????????t?=?new?myThread();
???????????????????????t.start();
???????????????????????break;
?????????????????????case?102:
???????????????????????????? finish();
???????????????????????break;
?????????????????????}
???????????}
//------------------------------------------------------?????????????
class?EHandler?extends?Handler {????????????????????????????????????//文章长度有限,代码请参考上例
??//------------------------------------------------------?????????????
class?myThread?extends?Thread{
????????????private?EHandler?mHandler;
public?void?run() {
????????????????Looper myLooper, mainLooper;
????????????????myLooper = Looper.myLooper();
????????????????mainLooper = Looper.getMainLooper();
????????????????String obj;
????????????????if(myLooper ==?null){
???????????????????????mHandler?=?new?EHandler(mainLooper);
???????????????????????obj =?"current thread has no looper!";
????????????????}
????????????????else?{
?????????????????????mHandler?=?new?EHandler(myLooper);
?????????????????????obj =?"This is from current thread.";
????????????????}
????????????????mHandler.removeMessages(0);
????????????????Message m =?mHandler.obtainMessage(1, 1, 1, obj);
????????????????mHandler.sendMessage(m);
?????????????}
??}
}
?
?
Android会自动替主线程建立Message Queue。 在这个子线程里并没有建立Message Queue。所以,myLooper值为null,而mainLooper则指向主线程里的Looper对象。于是,执行到指令:
mHandler =?new?EHandler(mainLooper);?此mHandler属于主线程。
指令:mHandler.sendMessage(m);
就将消息m存入到主线程的Message Queue里。mainLooper看到Message Queue里有消息,就会处理之,于是由主线程执行到mHandler的handleMessage()函数来处理消息。此程序输出画面为: