在安卓中线程内部与线程之间是通过Message来通讯的,这也就是传说中说的消息机制,很久都没理解。
首先来看看这几个类把:
1.Message
消息类,也就是被要Handler封装的消息,然后send。
注意这个类几个比较重要的字段
a.arg1和arg2:我们可以使用两个字段用来存放我们需要传递的整型值,在Service中,我们可以用来存放Service的ID。
b.obj:该字段是Object类型,我们可以让该字段传递某个多项到消息的接受者中。
c.what:这个字段可以说是消息的标志,在消息处理中,我们可以根据这个字段的不同的值进行不同的处理,类似于我们在处理 Button事件时,通过switch(v.getId())判断是点击了哪个按钮。
在使用Message时,我们可以通过new Message()创建一个Message实例,但是Android更推荐我们通过Message.obtain()或者Handler.obtainMessage()获取Message对象。这并不一定是直接创建一个新的实例,而是先从消息池中看有没有可用的Message实例,存在则直接取出并返回这个实例。反之如果消息池中没有可用的Message实例,
则根据给定的参数new一个新Message对象。通过分析源码可得知,Android系统默认情况下在消息池中实例化10个Message对象。
2.MessageQueue
消息队列,用来存放Message对象的数据结构,按照“先进先出”的原则存放消息。存放并非实际意义的保存,而是将Message对象以链表的方式串联起来的。MessageQueue对象不需要我们自己创建,而是有Looper对象对其进行管理,一个线程最多只可以拥有一个MessageQueue。我们可以通过Looper.myQueue()获取当前线程中的MessageQueue。
3.Looper
循环器,一直不断的循环从消息队列中取出消息。在一个线程中,如果存在Looper对象,则必定存在MessageQueue对象
,并且只存在一个Looper对象和一个MessageQueue对象。在Android系统中,除了主线程有默认的Looper对象,其它线程默认是没有Looper对象。如果想让我们新创建的线程拥有Looper对象时,我们首先应调用Looper.prepare()方法,然后再调用Looper.loop()方法。典型的用法如下:
class ChildThread extends Thread{
public void run(){
Looper.prepare() ;
..........;
Looper.loop();
}
}
4、Handler
消息处理者,可以处理消息、发送消息。
(个人理解):一个handler在哪个线程实例化就属于哪个线程,比如在主线程中Handler mainHandler= new Handler,这个mainHandler就属于主线程,这个mainHandler对应的消息队列就是主线程的消息队列。然后子线程要发送消息给主线程就需要通过主线程的mainHandler发送Message。反之,主线程要给子线程发送消息就需用子线程的handler发送消息。这样默认主线程中循环的looper才能取出消息。(纯属个人理解如有错误欢迎指证)
主线程和子线程交互:
package com.ch.demo;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class HandlerDemoActivity extends Activity {
private Button button;
private TextView textView;
public final int SETMAIN=1;
public final int SETCHLID=2;
public final String TAG="<-HandlerDemoActivity->";
public Looper looper;
private Handler chlidHandler;
private Handler mainhandler=new Handler(){
public void handleMessage(Message msg) {
switch(msg.what)
{
case SETMAIN:
textView.setText((String)msg.obj);
if(chlidHandler!=null){
Message msg2=chlidHandler.obtainMessage();
msg2.what=SETCHLID;
msg2.obj= Thread.currentThread().getName()+"来自主线程的回复消息";
chlidHandler.sendMessage(msg2);
}
}
super.handleMessage(msg);
}
};
class Chlid implements Runnable{
public void run() {
Looper.prepare();
chlidHandler=new Handler(){
public void handleMessage(Message msg) {
switch(msg.what)
{
case SETCHLID:
Log.i(TAG, msg.obj.toString());
}
}
};
Message msg=mainhandler.obtainMessage();
msg.what=SETMAIN;
msg.obj= Thread.currentThread().getName()+"来自子线程消息";
mainhandler.sendMessage(msg); //主线程的handler将消息压到主消息队列中。主线程的looper是启动着的
Looper.loop();
}
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
button=(Button) findViewById(R.id.button);
textView=(TextView) findViewById(R.id.text);
button.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
new Thread(new Chlid()).start();
}
});
}
}
运行结果: