活用Android的Message Queue(二)

活用Android的Message Queue(2)1.???????复习Message Queue的角色在上一篇里,介绍了Android的Thread、Loope

活用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()函数了。显示出画面如下:

?

? 活用Android的Message Queue(二)

?图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