阅读了相关的异步消息机制以及郭神的异步消息处理机制http://blog.csdn.net/guolin_blog/article/details/9991569,我这里做一个简要的笔记总结:
应用程序的主线程中会始终存在一个Looper对象,从而不需要再手动去调用Looper.prepare()方法.
总结一下就是在主线程中可以直接创建Handler对象,而在子线程中需要先调用Looper.prepare()才能创建Handler对象.
尝试在程序中创建两个Handler对象,一个在主线程中创建,一个在子线程中创建.
在子线程中创建的Handler是会导致程序崩溃的,提示的错误信息为 Can’t create handler inside thread that has not called Looper.prepare() 。
new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
handler2 = new Handler();
}
}).start();
在Handler的构造函数中,会调用Looper.myLooper()来获取一个Looper对象。如果Looper对象为空,则会抛出一个运行时异常,提示的错误正是 Can’t create handler inside thread that has not called Looper.prepare()。
而Looper.prepare()方法可以为其生成一个Looper对象。所以我们要先调用Looper.prepare()方法,才能创建Handler对象。
而在UI主线程则不用调用Looper.prepare(),因为ActivityThread(如果你不知道ActivityThread是什么,可以阅读我的上篇阅读笔记–Framework框架:重要类,APK运行过程,客户端的线程 http://blog.csdn.net/u014639129/article/details/52434512)中的main()方法会调用Looper.prepare(),不需要再手动去调用Looper.prepare()方法。
Handler.sendMessage()方法发送出去,然后在Handler.handMessage()里面进行消息处理。
其实是这样的:
Handler.sendMessage() 会把参数message和延迟时间uptimemillis传到MessageQueue的enqueueMessage(message,uptimemillis)。MessageQueue它是一个消息队列,用于将所有收到的消息以队列的形式进行排列,并提供入队和出队的方法。
1.MessageQueue并没有使用一个集合把所有的消息都保存起来,它只使用了一个mMessages对象表示当前待处理的消息,用next属性指定了下一个消息(形成一个队里),入队其实就是将所有的消息按时间来进行排序,调用msg.next,从而为每一个消息指定它的下一个消息是什么.它的简单逻辑就是如果当前MessageQueue中存在mMessages(即待处理消息),就将这个消息出队,然后让下一条消息成为mMessages,否则就进入一个阻塞状态,一直等到有新的消息入队。每当有一个消息出队,就将它传递到msg.target的dispatchMessage()。
这是源码:
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg); //这里就回到了最原始的handler.handleMessage(msg)方法了。
}
}
在Handler的dispatchMessage()方法中原来有做一个检查,如果Message的callback等于null才会去调用handleMessage()方法,否则就调用handleCallback()方法。
使用异步消息处理的方式就可以对UI进行操作:
由于Handler总是依附所在线程的,在子线程是无法操作ui的,于是通过发送消息,入队,出队,最后调用handleMessage(msg)的时候,是在主线程运行的,所有实现了UI的操作。
除了发送消息之外,我们还有以下几种方法可以在子线程中进行UI操作:
1.Handler的post()方法
实际就是调用sendMessageDelayed(getPostMessage(r), 0); 并且为Message设置一个CallBack回调。在dispatchMessage里面,CallBack不为空,则调用。
2.View的post()方法
实际就是调用Handler的post()方法。
3.Activity的runOnUiThread()方法
实际就是调用Handler的post()方法。或者直接调用runnable.run();(在主线程)