定义:
Message:消息,包含ID,消息处理对象及消息数据,由MessageQueue统一管理,最总由Handler处理
Handler:消息处理者,负责Message的发送及处理。
MessageQueue:消息对象,用来存放Handler发送过来的消息,按FIFO顺序。
Looper:消息循环者,不断地从MessageQueue中抽取Message执行。因此,一个MessageQueue需要一个Looper。
三者关系如下:
上图详细说明了消息处理的整个流程。
以下使用handler消息机制时的几个要点:
1.handler可以在任意线程发送消息(UI主线程或者工作线程),这些消息会被添加到关联的MQ上。
2.handler是在它关联的looper线程中处理消息的。
android 主线程也是一个Looper线程,所以普通的做法就是在主线程中new handler对象出来,然后使用这个hanlder来发送和处理消息,并直接可以在当前的主线程中更新UI界面。
所以利用handler一个常用的解决方案是Activity中创建handler,并将引用传递给worker thread(工作线程),工作线程执行完异步任务后使用handler发送消息,通知UI更新界面。
下面一个简单的例子:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/handler"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="handler message " />
</LinearLayout>
/**
* Copyright (C) 2012 HongCheng System Inc.
*/
package com.android.handler;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.TextView;
/**
* @author yangjp
* @version V1.0
*/
public class HandlerActivity extends Activity {
private TextView textView = null;
private Handler handler = null;
/*
* (non Javadoc)<p>Title: onCreate</p><p>Description: </p>
*
* @param savedInstanceState
*
* @see android.app.Activity#onCreate(android.os.Bundle)
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.handler);
textView = (TextView)findViewById(R.id.handler);
handler = new MyHandler(textView);
Thread thread = new WorkerThread(handler);
thread.start();
}
/**
* 工作线程
*@author yangjp
*@version V1.0
*/
private class WorkerThread extends Thread{
private Handler handler = null;
public WorkerThread(Handler handler){
this.handler = handler;
}
public void run() {
try {
Thread.sleep(1000 * 5);
// 暂停5秒
Message message = handler.obtainMessage();
message.what = 1;
message.arg1 = 100;
handler.sendMessage(message);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* 消息处理者
*@author yangjp
*@version V1.0
*/
private class MyHandler extends Handler{
private TextView textView = null;
public MyHandler(TextView textView){
this.textView = textView;
}
/*(non Javadoc)
*<p>Title: handleMessage</p>
*<p>Description: </p>
*@param msg
*@see android.os.Handler#handleMessage(android.os.Message)
*/
@Override
public void handleMessage(Message msg) {
// 处理消息,更新UI界面
switch(msg.what){
case 1:
String result = "执行结果进度:" + msg.arg1;
textView.setText(result);
break;
}
}
}
}
在主线程(UI线程)里,如果创建Handler时不传入Looper对象,那么将直接使用主线程(UI线程)的Looper对象(系统已经帮我们创建了);在其它线程里,如果创建Handler时不传入Looper对象,那么,这个Handler将不能接收处理消息。在这种情况下,通用的作法是:
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}
在创建Handler之前,为该线程准备好一个Looper(Looper.prepare),然后让这个Looper跑起来(Looper.loop),抽取Message,这样,Handler才能正常工作。
因此,Handler处理消息总是在创建Handler的线程里运行。而我们的消息处理中,不乏更新UI的操作,不正确的线程直接更新UI将引发异常。因此,需要时刻关心Handler在哪个线程里创建的。
1. Activity.runOnUiThread(Runnable)
2. View.post(Runnable)
3.View.postDelayed(Runnable, long)
4. Handler
注意:在post(Runnable action)方法里,View获得当前线程(即UI线程)的Handler,然后将action对象post到Handler里。在Handler里,它将传递过来的action对象包装成一个Message(Message的callback为action),然后将其投入UI线程的消息循环中。在Handler再次处理该Message时,有一条分支(未解释的那条)就是为它所设,直接调用runnable的run方法。而此时,已经路由到UI线程里,因此,我们可以毫无顾虑的来更新UI。
不确定当前线程时,更新UI时尽量调用post方法。