Android消息机制:
- 主要是指Handler的运行机制,同时Handler需要MessageQueue和Looper的支持.
Handler的主要作用:
- 将一个任务切换到某个指定的线程中执行
Android中使用消息机制的原因:
- Android系统规定UI只能在主线程进行,如果在非主线程中执行会抛出异常,线程的检验由ViewRootImpl的checkThread方法完成.
void checkThread() {
if (mThread != Thread.currentThread()) {
throw new CalledFromWrongThreadException("Only the original thread that created a view hierarchy can touch its views.");
}
}
- 主线程不能执行耗时操作,只能通过子线程进行耗时操作后通知界面刷新.
Handler工作过程:
Handler工作过程.pngMessageQueue创建和工作原理
- MessageQueue虽然名为消息队列,但是内部的数据结构使用的是单链表,因为单链表插入和删除效率较高.
- MessageQueue主要作用就是对消息进行插入和读取操作,插入方法为enqueueMessage(),读取方法为next()
- MessageQueue在Looper创建的时候创建
由于Looper是使用ThreadLocal保存的,由此得知每一个线程都只有一个Looper和一个MessageQueue
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
...
}
- Handler通过post或者send方法将消息发送到MessageQueue,由于Handler所有的post和send相关方法都会最终执行到enqueueMessage方法,而Handler的enqueueMessage方法会调用MessageQueue的enqueueMessage方法,所以就将消息加入到了消息队列中.
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
-
在MessageQueue的enqueueMessage方法中,主要的操作只是将所有的消息进行单链表的插入操作.
-
在MessageQueue的next()方法中,对队列进行无限循环,直到有新的消息插入,next方法就会返回这条消息,并从链表中删除这条消息.
Looper的工作原理
-
在消息机制中,MessageQueue扮演的角色只是一个消息存储的对象.而Looper就是不断遍历从MessageQueue,查询是否有信息消息加入,如果有就会通知Handler进行处理,否则就一直在循环遍历.
-
在手动创建的线程中默认是没有Looper的,因为Thread是Java的类,而Looper是Android提供的类,所以手动创建Thread后,需要提供一个Looper对象,才能正确的开启消息轮训.
-
创建Looper的方法,通过Looper的静态方法prepare初始化,然后调用loop方法进行小心轮训.
new Thread(){
@Override
public void run() {
Looper.prepare();
Handler handler = new Handler();
Looper.loop();
}
}.start();
- Looper中最重要的方法是loop,只有调用了loop方法才能开启对MessageQueue的轮训,对消息进行处理.在loop中会调用MessageQueue的next方法来获取消息,然后通过调用Handler的dispatchMessage方法进行消息的处理,而dispatchMessage方法是在创建Looper的线程中执行的,所以这样就将任务切换到了不同的线程中去了.
- Handler的创建必须有Looper,经常使用的空参数Handler其实已经默认获取到了主线程的Looper.
Handler工作原理
- Handler的工作主要包含消息发送和消息接收过程.
- 消息的发送可以通过一系列post和send方法实现,不过最终也是会调用到sendMessageAtTime方法.
- Handler发送消息的过程其实只是向MessageQueue中插入了一条消息,Looper会调用MessageQueue的next方法获取到这条消息,Looper获取到消息后,再交给Handler进行处理,即Handler的dispatchMessage方法会被调用,这样消息的发送过程就完成了.进入到消息处理.
Handler的dispatchMessage具体执行流程
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
在消息处理阶段,优先判断Message的CallBack是否为null,而这个callBack实际上就是handler的post方法传递进行来Runnable,然后就调用handleCallback方法,其实只是简单的调用Runnable中的run方法.
private static void handleCallback(Message message) {
message.callback.run();
}
当Callback为空,则检查mCallback接口是否为null,不为null就调用mCallback的handleMessage方法.mCallback其实是Handler的一个接口,可以在创建Handler的时候作为构造参数.
//CallBack接口使用方法
Handler handler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
return false;
}
});
调用了mCallback的handleMessage方法后,如果返回了true,这条消息已经被正确处理,如果返回false,最终调用Handler的handleMessage方法,结束消息处理过程.
Handler消息处理流程图.png
网友评论