当前位置: 代码迷 >> Android >> 活用Android的Message Queue(一)
  详细解决方案

活用Android的Message Queue(一)

热度:184   发布时间:2016-05-01 14:34:11.0
活用Android的Message Queue(1)

1.??Message Queue的角色

l???在你的Android程序里,新创建一个线程,或称线程(Thread)时,并不会自动建立其Message Loop

l???Android里并没有GlobalMessage Queue数据结构,例如,不同APK里的对象不能透过Massage Queue来交换消息(Message)

l???一个线程可以创建一个Looper对象,由它来管理此线程里的Message Queue

l???你可以创建Handler对象来与Looper沟通,以便push新消息到Message Queue里或者接收Looper(Message Queue取出)所送来的消息。

l???线程AHandler对象引用可以传递给别的线程,让别的线程BC等能发送消息来给线程A(存于AMessage Queue)

l???线程AMessage Queue里的消息,只有线程A所属的对象可以处理之。

l???使用Looper.myLooper可以取得目前线程的Looper对象引用。

l???使用mHandler =?new?EventHandler(Looper.myLooper());可创建用来处理目前线程的Handler对象;其中,EventHandlerHandler的子类别。

l???使用mHandler =?new?EventHandler(Looper.getMainLooper());可创建用来处理main线程的Handler对象;其中,EventHandlerHandler的子类别。

?

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里有消息,就会处理之,于是由主线程执行到mHandlerhandleMessage()函数来处理消息。此程序输出画面为:

  相关解决方案