看过冷冰的Android核心分析第十一篇:Android GWES之消息系统,我得到了一张重要的图:
对照源码看这张图之后,我发现冷冰已经总结的很清晰。我补充我认识到的另外几点看法和疑问:
1.MessageQueue对外来说基本是不可见的,我们要为自己的程序添加消息处理机制时无需关心的(当然无需关心,这一点好勉强,^_^)
2.在Looper中有这么一段
private static final ThreadLocal sThreadLocal = new ThreadLocal();
因此,即便在一个VM实例中存在多个消息处理框架,线程相关的资源依旧是共享的。(不过ThreadLocal等概念我还得普及一下)
3. 阅读Handler代码发现一个很有趣的地方,先看代码:
在Message中有这么一段:
/*package*/ Runnable callback;
在Handler中有这么一个方法:
private final void handleCallback(Message message) {
message.callback.run();
}
而这个handleCallback方法是在handleMessage时调用的:
/**
* Subclasses must implement this to receive messages.
*/
public void handleMessage(Message msg) {
}
/**
* Handle system messages here.
*/
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
哈,这让我想起了以前写js代码时那种回调风格。。我以前看到的或者用到的回调大多是自己定义一个接口,折腾了一圈才发现,原来有现成的啊,竟然不懂得用。。
4. 从Message类中的next变量和obtain方法看出,Message从结构上来看,就像一个链表,没有方向,没有优先级概念(那如果消息存在优先级的话,这个框架还能搞定吗?当然是不能)。试想一下,在GWES模型中,会不会出现一种情况,某些事件的优先级要高于其它而要优先处理的呢?如果碰到这种情况该怎么处理?
今天看相关源码发现,Android消息处理框架,没有优先级这一说。我们在sendMessage的时候最多能加上一个delay time作为参数,所以框架的使用者如果需要达到某些消息优先处理,那么可以通过这个delay time来实现。(是不是有点别扭,没事,习惯了就好……但,还是有点别扭)
考虑一下Android手机的系统特性,每个手机都会一个菜单键、Home键和back键,那么在什么情况下会存在一些优先级较高的消息呢,我目前还没想出来,因为在一个Activity里面,所有view component的地位都应该是相等的,所以每个component的消息处理也应该是同级的,如果某个应用中需要处理一些特别的(例如定时、延迟)消息,可以采用Task来处理定时任务,延迟也只要加上delay time参数即可。对于back键的处理Activity是单独开来的,开发者需要在onBackPresssed中自行处理,menu键和这是一样的,Home键开发者根本没法控制的,系统会自动处理(onPause --> onStop)。其实这几个键事件也是我目前能想到的需要特别处理的地方。
5. 首先来看一段代码:
final boolean enqueueMessage(Message msg, long when) {
if (msg.when != 0) {
throw new AndroidRuntimeException(msg
+ " This message is already in use.");
}
if (msg.target == null && !mQuitAllowed) {
throw new RuntimeException("Main thread not allowed to quit");
}
synchronized (this) {
if (mQuiting) {
RuntimeException e = new RuntimeException(
msg.target + " sending message to a Handler on a dead thread");
Log.w("MessageQueue", e.getMessage(), e);
return false;
} else if (msg.target == null) {
mQuiting = true;
}
msg.when = when;
//Log.d("MessageQueue", "Enqueing: " + msg);
Message p = mMessages;
if (p == null || when == 0 || when < p.when) {
msg.next = p;
mMessages = msg;
this.notify();
} else {
Message prev = null;
while (p != null && p.when <= when) {
prev = p;
p = p.next;
}
msg.next = prev.next;
prev.next = msg;
this.notify();
}
}
return true;
}
这段代码是MessageQueue中将某个message加入消息队列的方法,这里我注意到两点:
1. 没有使用容器类来充当一个message pool,而是每个message对象都会有一个next字段用以引用它的下一个,所以message是以对象间链式的引用来存储的(message会被Looper处理,所以不用担心对象会释放掉造成数据丢失;没有用到集合类,简化了数据结构和操作)
2.那个while循环是进行排序的,它会对每个新进来的message对象按照when(就是delay time)进行排序,因为是链式数据结构,所以效率相当高(不过我没测试过有多高)
引申:这个算法让我对数据结构又有一点新的认识。以前我总是条件反射的以为,任何数据都会以某种容器来存储(我惯用ArrayList、Map等什么的),但是我却忽视了一点,什么是容器,我曾经看过ArrayList或者其它的代码,它们内部都会有一个数组结构来存储数据,如果数据超出数组边界,那么就新创建一个数组把原来的数据拷贝进去(System.arrayCopy)再把旧数组替换掉(Map什么的我具体忘记了,但是我估计也不出这左右),所以,数组是最基本结构;除此之外,任何new出来的对象都应该是某种数据结构,它们用字段存储数据,只是它们没有名字而已(像List,Map等这样的数据结构领域的名字)。到这,就不难理解为什么googler可以用对象之间的相互引用来实现某种数据存储,因为,任何这种那样的方式的本质是没有改变的:一种映射,语言标记到计算机存储之间的映射,通过使用标记就能明确访问这个标记所对应的计算机上存储的数据。
分享到:
相关推荐
Android 异步处理 Handler+Looper+MessageQueue深入详解
Handler获取当前线程中的looper对象,looper用来从存放Message的MessageQueue中取出Message,再有Handler进行Message的分发和处理. 简单定义: 1、Message Queue(消息队列): 用来存放通过Handler发布的消息,通常...
Handler+Looper+MessageQueue
Looper MessageQueue 源码解析,通过源码 手写一套自己的Handler。
Message,MessageQueue,Looper,Handler详解
Looper,MessageQueue,Handler分析之ActivityThread.java
Handler 在 MessageQueue 中以任务形式排队,Looper 在任务出现时执行它们 MessageQueue. Looper 使线程保持活动状态,循环 MessageQueue 并向相应 Handler 的进程发送消息。 Thread 通过调用 Looper 的 quit() ...
handler与looper及messagequeue的简单总结
android源码中包含了...android的消息处理有三个核心类: Looper,Handler和Message。 其实还有一个Message Queue(消息队列) , 但是MQ被封装到Looper里面了, 我们不会直接与 MQ打交道, 因此我没将其作为核心类。
安卓应用开发基础的消息处理机制分析。对应用工程师很有帮助。
Message(消息):需要被传递的消息,其中包含了消息标识(what),消息处理数据和处理对象(arg1,arg2,obj),发送该消息的Handler对象(target)等,由MessageQueue统一列队,最终由Handler处理。 MessageQueue(消息...
你可以诞生Handler之对象来与Looper沟通,以便push新讯息到Message Queue里;或者接收Looper(从Message Queue取出)所送来的讯息。 线程A的Handler对象参考可以传递给别的线程,让别的线程B或C等能送讯息来给...
Message:消息,其中包含了消息ID,消息处理对象以及处理的数据等,由MessageQueue统一列队,终由Handler处理。 Handler:处理者,负责Message的发送及处理。使用Handler时,需要实现handleMessage(Message msg)方法...
NULL 博文链接:https://null-point.iteye.com/blog/1356138
Message,MessageQueue,Looper,Handler详解[归类].pdf
本篇文章是对Handler,Looper与MessageQueue进行了详细的分析介绍,需要的朋友参考下
主要介绍了深入Android Handler,MessageQueue与Looper关系,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
我们知道android是基于Looper消息循环的系统,我们通过Handler向Looper包含的MessageQueue投递Message, 不过我们常见的用法是这样吧? 一般我们比较少接触MessageQueue, 其实它内部的IdleHandler接口有很多有趣的...
Android 是消息驱动的,实现消息驱动有几个要素: ...消息队列: MessageQueue 消息循环,用于循环取出消息进行处理: Looper 消息处理,消息循环从消息队列中取出消息后要对消 息进行处理: Handler
android的消息处理有三个核心类:Looper,Handler和Message。其实还有一个MessageQueue(消息队列),但是Message被封装到Looper里面了,我们不会直接与Message打交道,因此我没将其作为核心类。下面一一介绍下: ...