android消息传递机制由消息队列MessageQuenue,Looper,Handler三部分组成。
一.MessageQuenue
消息队列——存放消息Message的数据结构,按照FIFO(先进先出原则)。
Message对象
Message.what 可以用于标记一个消息
Message.object 可以用于传递消息的具体内容,也可以传递事件——Handler.post(runnable)中的runnable就是利用object传递的。
二.Looper
消息队列的管理者.
一个线程中如果有一个Looper必有一个MessageQuenue,而且一个线程最多有一个Looper必有一个MessageQuenue,
android中主线程默认有一个Looper和MessageQuenue,
如果想在自定义的线程中启用Looper,则使用Looper.prepare(),Looper.loop();
new Thread(){
@Overrride
public void run(){
Looper.prepare();
//其他操作
Looper.loop();
}
}.start();
也可以使用HanlderThread类——自带Looper
三.Handler
将消息添加进消息队列(
一般在子线程中调用Handler.sendMessage(Message)或Handler.post(Runnable);将消息添加进消息队列以实现与主线程间的通信
)
四。思路图
1-2
java实现线程通信的方法有两种,一种是共享变量的方式,一种是管道(Pipe)方式
从1-2可以看出,消息传递机制实际上使用的是共享变量的方式实现线程通信
五。实例代码
public class MessageDemoctivity extends Activity {
Button mBtn=null;
TextView mTxt=null;
Handler handler=new Handler() {
@Override
public void handleMessage(Message message){
if(message.what==1){
mTxt.setText((String)message.obj);
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_message_democtivity);
mBtn= (Button) findViewById(R.id.test_btn);
mTxt= (TextView) findViewById(R.id.test_txt);
mBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new Thread(){
@Override
public void run(){
try {
Thread.sleep(3*100);//模拟获取网络数据
} catch (InterruptedException e) {
e.printStackTrace();
}
Message message = Message.obtain();//获取已有Message对象或新建Message对象
message.what=1;
message.obj="message give you";
handler.sendMessage(message);//将Message添加进MessageQueune,Looper将Message交由Hanlder的handlerMessage处理
}
}.start();
}
});
}
}
六.源码分析
Hanlder
1.构建 Handler
创建Handler时如果没有指明关联的Looper则会默认关联当前线程的Looper(如果当前线程没有Looper则会报异常)
且会关联Looper中的消息队列
2.Handler.sendMessage(Message msg)
sendMessage(Message msg)-->
sendMessageDelayed(Message msg, long delayMillis)-->
sendMessageAtTime(Message msg, long uptimeMillis)-->
enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis)
Handler的enqueueMessage()方法调用消息队列的enqueneMessage()方法处理Message
——即将Message添加进MessageQuenue
3.Handler.post(Runnble runnable);
Handler的post方法是将Runnable赋予Message.callblack再
通过sendMessageDealyed最终在sendMessageAtTime()中将消息添加进消息队列中
Looper
Looper的Loop方法从MessageQuenue从取出Message,并交由Message关联的Handler----
msg.tartget的dispatchMessage处理。
而在Hanler的enqueueMessage()中msg.tartget=this,即msg.target关联的是当点当前Handler
dispathcMessage根据callback是否为null交由handlerCallback或者handleMessage处理
其中handleMessage通常是我们创建Handler时要覆盖的方法
而handlerCallback只是简单地调用callback的run()方法
总结 消息的处理最终是在Looper对象中处理的(
Handler将消息添加入消息队列,Looper从消息队列中取出消息,并有调用消息关联的Handler对象处理
),而Looper在主线程中,所以消息就由子线程转由主线程处理