活用Android的Message Queue(2)
1.???????复习Message Queue的角色
在上一篇里,介绍了Android的Thread、Looper、Message Queue和Handler四者间之关系。
先复习如下:
l???UI thread?通常就是main thread,而Android启动程序时(即创建Process时)会替它建立一个Message Queue。
l???当然需要一个Looper对象,来管理该Message Queue。
l???我们可以创建Handler对象来push新消息到Message Queue里;或者接收Looper(从Message Queue取出)所送来的消息。
l???线程A的Handler对象引用可以传递给别的线程,让别的线程B或C等能发送消息来给线程A(存于A的Message Queue里)。
l???线程A的Message Queue里的消息,只有线程A所属的对象可以处理之。
?
?了解了四者间之关系后,在本篇里,就能来思考如何让主线程与子线程之间互相沟通了。包括,子线程push消息到主线程的Message Queue里,并触发主线程去执行某项工作(即执行某个函数)。
?
2.??由别的线程发送消息到主线程的Message Queue(续)
????在上一篇文章里,使用如下程序片段:
//?class?ac01?extends?Activity {
??????????// ………
??????????????public?void?onClick(View v) {
?????????????????????switch(v.getId()){
?????????????????????case?101:
???????????????????????????t?=?new?myThread();
???????????????????????????t.start();
??????????????????????????break;
?????????????????????case?102:
??????????????????finish();
????????????????????????????????break;
?????????????????????}
???????????}
//------------------------------------------------------?????????????
class?EHandler?extends?Handler {
???????????????????public?EHandler(Looper looper) {
???????????????????????super(looper);
???????????????????}
???????????????????@Override
???????????????????public?void?handleMessage(Message msg) {
??????????????????????tv.setText((String)msg.obj);
???????????????}
???????????}
//------------------------------------------------------?????????????
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);
?????????????}
??}
}
??
这个mHandler定义于myThread类别里,而且由子线程执行指令:??????mHandler?=?new?EHandler(mainLooper);
来创建EHandler对象;但是这个mHandler确是属于main线程的(用来存取主线程的MessageQueue),所以指令:
mHandler.sendMessage(m);是将m丢到主线程的MessageQueue里。
此外,我们也可以将mHandler定义于ac01类别里。如下程序范例:
?
//----- Looper_03范例?-----
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;
????EventHandler?h;
????Context?ctx;
????public?void?onCreate(Bundle icicle) {
????????????super.onCreate(icicle);
????????????ctx?=?this;
????????????????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:
?????????????h?=?new?EventHandler(Looper.myLooper());
?????????????t?=?new?myThread();
?????????????t.start();
?????????????break;
????????case?102:
???????finish();
????????????break;
????????}
????}
//------------------------------------------------?????
public?class?EventHandler?extends?Handler {
????????????public?EventHandler(Looper looper) {
?????????????????super(looper);
?????????????}
?????????????@Override
?????????????public?void?handleMessage(Message msg) {
??????????????????????((Activity)ctx).setTitle((String)msg.obj);
?????????????}
??????????}
//------------------------------------------------------??????
class?myThread?extends?Thread{
?????public?void?run() {
????????????String obj =?"from myThread";
????????????Message m =?h.obtainMessage(1, 1, 1, obj);
????????????h.sendMessage(m);
??????}
??}
}
//------------------------------------------------------
?
指令:h?=?new?EventHandler(Looper.myLooper());
此h是属于main线程的(用来存取主线程的MessageQueue)。在myThread类别里的指令:h.sendMessage(m);
虽然是由子线程执行该指令,还是将m丢到主线程的MessageQueue里。于是,子线程所执行的run()函数,就顺利将m丢给主线程(的Message Queue),并触发了主线程去执行handleMessage()函数了。显示出画面如下:
?
? 
?图1??
?
上述的指令:
?
??????????myLooper = Looper.myLooper();
??????????mainLooper = Looper.getMainLooper();
????????????????………
??????????mHandler?=?new?EHandler(mainLooper);
??????????????????………
??????????mHandler?=?new?EHandler(myLooper);
????????????????????………
?
都明显地指明mHandler是负责存取哪一个线程的Message Queue。不过,有时候并不需要特别指明。例如上述的onClick()函数和EventHandler类别,可改写为:
?
//----- Looper_03aa?范例?-----
//?class?ac01?extends?Activity {
??????????// ………
???????public?void?onClick(View v) {
????????switch(v.getId()){
????????case?101:
?????????????h?=?new?EventHandler();
?????????????t?=?new?myThread();
?????????????t.start();
?????????????break;
????????case?102:
??????????????finish();
????????????break;
????????}
????}
//------------------------------------------------?????
public?class?EventHandler?extends?Handler {
?????????????@Override
?????????????public?void?handleMessage(Message msg) {
??????????????????????((Activity)ctx).setTitle((String)msg.obj);
?????????????}
??????????}
//------------------------------------------------------??????
class?myThread?extends?Thread{
?????public?void?run() {
????????????String obj =?"from myThread";
????????????Message m =?h.obtainMessage(1, 1, 1, obj);
????????????h.sendMessage(m);
??????}
??}
}
?
指令:h?=?new?EventHandler();? 就等于:h = new EventHandler(Looper.myLooper());
它建立了当前线程(Current Thread)的EventHandler对象。于此,是由main线程执行此指令的,所以此EventHandler对象是用来存取main线程的Message Queue。
上述程序将handleMessage()定义于EventHandler类别内,也可以直接定义于ac01类别之内。于是上述程序,也相当于:
?
//----- Looper_03bb?范例?-----
//?class?ac01?extends?Activity {
??????????// ………
??????????public?void?onClick(View v) {
????????switch(v.getId()){
????????case?101:
?????????????h?=?new?Handler(){
?????????????????public?void?handleMessage(Message msg) {
??????????????????????((Activity)ctx).setTitle((String)msg.obj);
?????????????}};
??????????????t?=?new?myThread();
?????????????t.start();
?????????????break;
????????case?102:
????????finish();
????????????break;
????????}
????}
//------------------------------------------------------??????
class?myThread?extends?Thread{
?????public?void?run() {
????????????String obj =?"from myThread...";
????????????Message m =?h.obtainMessage(1, 1, 1, obj);
????????????h.sendMessage(m);
??????}
??}
}
?
其执行结果是一样的。
?
转自:http://www.android1.net/Topic.aspx?BoardID=11&TopicID=631
