一、Looper, MessageQueue, Handler, Message之间的关系
Message:消息,其中包含了消息ID (what), 消息处理对象 (Handler target) 以及处理的数据等,由 MessageQueue 统一列队 (enqueueMessage), 最终由Handler处理。
Handler:处理者,负责Message的发送 (sendMessage) 及处理 (dispatchMessage->handleMessage). 使用Handler时,需要实现handleMessage(Message msg)方法来对特定的Message进行处理,例如更新UI等。
MessageQueue:消息队列,用来存放Handler发送过来的消息,并按照FIFO规则执行。当然,存放Message并非实际意义的保存,而是将Message以链表的方式串联起来的,等待Looper的抽取。
Looper:消息泵,不断地从MessageQueue中抽取Message, 然后调用由Message所指定 (target) 的具体某个Handler的dispatchMessage来对Message进行处理。
一个MessageQueue需要一个Looper。即一个线程只能有一个Looper和一个MessageQueue, 但是可以有多个Handler.
Thread:线程,负责调度整个消息循环,即消息循环的执行场所。
二、如何建立Handler的通信机制
- 初始化Looper
首先两个线程要分别建立各自的Looper和MessageQueue.
Note: 每个线程中Looper和MessageQueue只能有一个,而Handler可以有多个。
Looper.prepare();
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
一个线程在调用Looper的静态方法prepare()时,这个线程会新建一个Looper对象,并放入到线程的局部变量中,而这个变量是不和其他线程共享的。看看Looper()这个构造函数,
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
可以看到在 Looper的构造函数中,新建了一个final MessageQueue. 获得Looper绑定的线程。
- 绑定handler到线程实例的Looper对象
mHandler= new Handler(); 来看下具体的实现
public Handler(Callback callback, boolean async) {
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
} //mem leak的提示
mLooper = Looper.myLooper(); //获得当前的线程的Looper
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue; <span style="font-size: 14.6666669845581px; font-family: Calibri; widows: auto;">//获得当前的线程的 MessageQueue</span>
mCallback = callback;
mAsynchronous = async;
}
绑定过程:通过Looper的静态方法myLooper获得该线程的Looper,并赋值给handler中的mLooper, 同时也获得mQueue, mCallback.
- 自定义处理消息的方法
@override
handleMessage(Message msg) {
}
- 启动消息循环
Looper.loop(); //loop是一个静态方法
public static void loop() {
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
// This must be in a local variable, in case a UI event sets the logger
Printer logging = me.mLogging;
msg.target.dispatchMessage(msg);
msg.recycle();
}
}
myLooper获得当前线程的looper, 在prepare函数中设置到sThreadLocal中
public static Looper myLooper() {
return sThreadLocal.get();
}
queue = me.mQueue //获得当前线程的MessageQueue. 在new Looper()中初始化
for (;;) {
Message msg = queue.next(); // might block
msg.target.dispatchMessage(msg);
...
msg.recycle();
}
}
接着在一个 for 死循环里,不断的遍历 MessageQueue 里的 message, 然后将该 message route 到创建该 message 的 target(handler) 的 dispatchMessage 里开始处理,而该 dispatchMessage 就是第 c 步覆写的 dispatchMessage()
到此一个Handler的事件处理就建立起来了。
三、Message的生成与发送
接下来看下Message是怎么建立的,有两种方法
- 用直接 new Message(), 然后手动填上what, arg1, arg2, target
用Message里的静态obtain()方法,传入handler, what, arg1, arg2
- 在telephony中方法1用得比较少,用得最多的是用 Handler的obtainMessage(),
事实上obtainMessage()最终也是调用的Message.obtain(),这样有个好处是直接用当前handler了。
如: obtainMessage()
public final Message obtainMessage(int what)
{
return Message.obtain(this, what); //this指当前的handler
}
Message创建 好后,是怎么 发 送到 target的MessageQueue里 的呢?
public void sendToTarget() {
target.sendMessage(this);
}
T arget也就 是 传 入的handler
sendMessage->sendMessageDelayed->sendMessageAtTime
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue = mQueue; //找到线程的MessageQueue
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis); //Message enqueue
}
最后 调用 到MessageQueue里 的enqueueMessage
//下面这个DEMO是用来测试主线程和子线程互发消息的例子。
public class MainActivity extends Activity implements OnClickListener {
Button mButton;
LooperThread mThread;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mButton = (Button) findViewById(R.id.button);
mButton.setOnClickListener(this);
showLooper();
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button:
pressButton();
break;
default:
break;
}
}
private void pressButton() {
//开启一个线程
mThread = new LooperThread();
mThread.start();
}
//线程
class LooperThread extends Thread {
public Handler mLooperThreadHandler;
@Override
public void run() {
Looper.prepare(); //将LooperThread初始化为一个Looper
mLooperThreadHandler = new LooperThreadHandler(Looper.myLooper());
showLooper();
Message msg = Message.obtain();
msg.what = 100;
mHandler.sendMessage(msg); //往主线程发送消息
Looper.loop();
}
}
private class LooperThreadHandler extends Handler {
public LooperThreadHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
log("Looper Handler received "+msg.what);
showLooper();
}
}
private Handler mHandler = new Handler() {
@Override
public void dispatchMessage(Message msg) {
log("Main:" + "received " + msg.what);
showLooper();
//往子线程里发送消息
Message msg1 = mThread.mLooperThreadHandler.obtainMessage(1000);
mThread.mLooperThreadHandler.sendMessage(msg1);
}
};
private void showLooper() {
log("In Looper:"+Looper.myLooper());
log("Current thread:"+Thread.currentThread());
log("-------------------------------------");
}
private void log(String str) {
Log.d("bobby", str);
}
}
以下是打印的log
D/bobby ( 5492): In Looper:Looper (main, tid 1) {4243e4a8}
D/bobby ( 5492): Current thread:Thread[main,5,main]D/bobby ( 5492): -------------------------------------
D/bobby ( 5492): In Looper:Looper (Thread-2159, tid 2159) {425afe68}
D/bobby ( 5492): Current thread:Thread[Thread-2159,5,main]
D/bobby ( 5492): -------------------------------------
D/bobby ( 5492): Main:received 100
D/bobby ( 5492): In Looper:Looper (main, tid 1) {4243e4a8}
D/bobby ( 5492): Current thread:Thread[main,5,main]
D/bobby ( 5492): -------------------------------------
D/bobby ( 5492): Looper Handler received 1000
D/bobby ( 5492): In Looper:Looper (Thread-2159, tid 2159) {425afe68}
D/bobby ( 5492): Current thread:Thread[Thread-2159,5,main]
D/bobby ( 5492): -------------------------------------
四、AsyncResult
在telephony中,在Message处理中用得比较多还有AsyncResult
在RIL.java processSolicited中对每个回来的Request都会
if (error != 0) { // Request有exception
rr.onError(error, ret);
/*** 传入exception,该exception是从QCRIL里返回的。
if (mResult != null) {
AsyncResult.forMessage(mResult, ret, ex);
mResult.sendToTarget();
}
***/
} else { //Request没有exception
if (rr.mResult != null) {
AsyncResult.forMessage(rr.mResult, ret, null);
//rr.mResult是一个Message, 将返回的AsyncResult封装进入Message.obj, AsyncResult包
//含Request 的结果,以及一些异常结果
rr.mResult.sendToTarget();
}
}
=========== AsyncResult.java
/** Saves and sets m.obj */
public static AsyncResult
forMessage(Message m, Object r, Throwable ex)
{
AsyncResult ret;
ret = new AsyncResult (m.obj, r, ex);
m.obj = ret;
return ret;
}
/** please note, this sets m.obj to be this */
public
AsyncResult (Object uo, Object r, Throwable ex)
{
userObj = uo;
result = r;
exception = ex;
}
五、Registrant, RegistrantList
在讲Registrant之前,首先来看一段代码
这个函数广泛的用在telephony中,当卡状态变化了,就需要通知注册该函数的Handler.
那么这种通知是如何实现的呢。Registrant.java, RegistrantList.java
protected RegistrantList mIccChangedRegistrants = new RegistrantList();
new 一个 RegistrantList 对象, 会在RegistrantList类里会自动new一个ArrayList,用来保存所有加入的单个Registrant
public
Registrant(Handler h, int what, Object obj)
{
refH = new WeakReference(h);//定义一个弱引用
this.what = what; //不同的事件
userObj = obj;
}
public synchronized void
add(Registrant r)
{
removeCleared(); //将已经被回收了的Handler从Registrants里移出
registrants.add(r);
}
new 一个 Registrant对象, 并将该对象加入到 registrants中。
r.notifyRegistrant() -> r. internalNotifyRegistrant()
internalNotifyRegistrant (Object result, Throwable exception)
{
Handler h = getHandler(); //new Registrant对象时传入的Handler
if (h == null) {
clear();
} else {
Message msg = Message.obtain(); //生成一个Message对象
msg.what = what; //
msg.obj = new AsyncResult(userObj, result, exception);
//用AsyncResult的方法
h.sendMessage(msg); //将消息发送到MessageQueue里处理
}
}
Registrant/RegistrantList的通知机制都是based on Handler/Message/MessageQueue上的。
参考:
http://www.cnblogs.com/xirihanlin/archive/2011/04/11/2012746.html
http://blog.csdn.net/oracleot/article/details/19163007
http://blog.163.com/gobby_1110/blog/static/29281715201161911349440/
http://blog.csdn.net/mylzc/article/details/6771331