Android 消息系统解析(Handler.class及相关类源码解析)
来源:互联网 发布:物资采购软件 百度云 编辑:程序博客网 时间:2024/05/17 04:39
额,新手,第一次发文章...前几天写文档的时候发现网上的教程。。都不是很详细,反正不是很适合我这种新手....所以在整理之后就发上来了。顺便,不会弄目录,大家将就着看下吧。。
1.Handler概念 2
1.1为什么要用Handler 2
1.2 Handler运行流程 2
1.3 Handler的作用 2
1.4 Handler的作用 3
2.Handler.class源码解析 5
2.1 Handler的构造方法 5
2.2 Handler对消息的发送 6
2.3 Handler对消息的处理 8
3、 代码具体分析 8
3.1 Message.class 8
3.1.1Message.class各属性解析 8
3.2 MessagePool消息池原理及代码分析 9
3.2.1 Message的构造方法 9
3.2.2为什么要创建消息池 10
3.2.3 MessagePool的建立 11
3.2、Looper源码解析 11
3.2.1 Looper.prepare();方法解析 12
3.3、ThrealLocal<T> 13
ThreadLocal<T>概述 14
ThreadLocal<T>的接口方法 14
实现原理/流程图 15
Thread与同步机制比较 15
Threadlocal小结 16
为什么要在Looper中使用ThreadLocal 16
3.4 Looper.loop();-----------启动消息循环 16
3.5、MessageQueue.class源码分析 17
3.5.1 MessageQueue类的介绍: 17
3.5.2 IdleHandler接口解析; 18
3.5.3 next()方法解析; 19
3.6 equeueMessage方法解析
以下内容只是对Handler、Message、MessageQueue、Looper、的源代码以及相关知识的一个简单的解析,至于深入的分析还没有涉及,如果有错误请大家多多指正,共同学习,谢谢!
1. Handler概念
1.1为什么要用Handler
在Android里,子线程不能更改主线程的UI
一般来说,所有显示在界面上的控件,都是由主线程创建的
每个主线程都有一个Handler,Handler运行在主线程里,它与子线程可以通过Message对象来传递数据
1.2 Handler运行流程
主线程里都维护了一个消息对列(message queue),子线程通过Message实例设置消息内容,通过主线程里的Handler实例把消息发送到消息队列(message queue),在主线程里还有一个轮循器(looper)在检查消息对列里有没有新的消息,一旦发现有新的消息,looper就会交给Handler对象处理,
Handler则调用自己的回调函数HandlerMessage来更新UI或者其它操作。
1.3 Handler的作用
调度消息和Runnable对象去被执行;使动作在不同的线程中运行
注:Handler对Message的处理并不是并发的。
1) 一个Looper 只有处理完一条Message才会读取下一条,所以消息的处理是阻塞形式的。但是如果用不同的Looper则能达到并发的目的
2)Handler能够让你发送和处理消息,以及Runnable对象,每个Handler对象对应唯一的Thread和MessageQueue。
3)当你创建一个Handler对象之后,它就与MessageQueue绑定在一起了
4)当一个应用程序中进程被创建时,它的主线程专门运行消息队列(MessageQueue),去管理顶层的应用程序相关的对象,eg:activity,broadcastReceiver等
综上所述:Handler做了以下几件事
1)运行在某个线程上,共享该线程的消息队列
2)接收消息 、调度消息、派发消息、处理消息
3)实现消息的异步处理
1.4 Handler的作用
图1:简单的子线程发送信息给UI线程图例
图2:主线程与子线程进行交互的图例
从这个流程图中我们可以从中找到几个被用到的类
Message: 就是消息原型,包含消息的描述与数据
MessageQueue: 就是消息队列,存放消息的地方,每个线程最多只能拥有一个MessageQueue
Looper: MessageQueue的管理者,每个线程只能有一个Looper
Handler: 统领Message.class、MessageQueue.class、Looper.class
2. Handler.class源码解析
从官方文档中分析, Handler的主要作用是能够让你发送和处理消息/Runnable对象,每一个Handler对应一个Thread和一个Thread的消息队列,当你创建一个Handler的时候,它就和Thread的消息队列绑定在一起,然后就可以传递消息或者Runnable对象给消息队列
当一个应用程序被创建时,它的主线程专门运行消息队列MessageQueue去管理顶层的应用程序相关的对象,例如:activity、broadcastReceiver等,你可以创建你的Thread,通过主线程的Handler对象与主线程进行交互,发送message或者runnable对象给主线程,交互的方法就是通过handler.post/sendMessage
类中的全局变量
final MessageQueue mQueue;
final Looper mLooper;
final Callback mCallback;
IMessenger mMessenger;
2.1 Handler的构造方法
public Handler() {
public Handler(Callback callback) {
public Handler(Looper looper) {
public Handler(Looper looper, Callback callback) {
publicHandler(boolean async) {
public Handler(Callback callback, boolean async) {
在线程中创建Handler对象时,需要做以下工作:
1.获取Thread中的Looper对象交给Handler的成员变量引用维护
2.通过Looper对象获取MessageQueue交给Handler的成员变量引用维护在使用Handler时,需要重写handlerMessage方法(消息处理的方法)
举例:Handler handler = newHandler(){
publicvoid handleMessage(Message msg) {
switch (msg.what) {
case 1:break;
case 2:break;
case 3:break;
default:
break;
}
}
};
2.2 Handler对消息的发送
消息发送的两种方式:post和sendMessage
post():针对Runnable对象,Runnable是一个接口,就是一个回调函数(提供了run方法)
sendMessage():针对message对象
下面我们来看下代码:
Post:
publicfinalbooleanpost(Runnable r){
returnsendMessageDelayed(getPostMessage(r), 0);
}
privatestatic Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
publicfinalbooleansendMessageDelayed(Message msg, longdelayMillis){
if (delayMillis<0) {
delayMillis=0;
}
returnsendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
SendMessage :
publicfinalboolean sendMessage(Message msg){
return sendMessageDelayed(msg, 0);
}
publicfinalbooleansendMessageDelayed(Message msg, longdelayMillis){
if (delayMillis < 0) {
delayMillis = 0;}
returnsendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
由上面的代码可以看出,不论是message还是runnable ,处理方式都是类似的
==================================================
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
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);//将消息插入队列
}
==================================================
2.3 Handler对消息的处理
public void handleMessage(Message msg) {
}
public void dispatchMessage(Message msg) {
//首先判断runnable对象
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) { //整个系统的回调函数
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);//消息处理
}
}
3、代码具体分析
3.1 Message.class
3.1.1 Message.class各属性解析
public int what;// 消息的标示
public int arg1; // 传递简单数据,用这个更比setData更能节省资源
public int arg2;// 同上
public Object obj;// 传递比较复杂的数据
public Messenger replyTo;//
/*package*/ long when;// 什么时候处理这个消息
/*package*/ Bundle data;// 传递比较复杂的数据
/*package*/ Handler target;//处理消息的目标handler
/*package*/ Runnable callback;// 消息派发时执行Runnable对象
/*package*/Message next;// 使消息形成链表,同时,构建消息池的链表结构
private static Message sPool;// 构建一个消息池
private static intsPoolSize = 0;// 消息池内的消息数量,初始值为0
private static final intMAX_POOL_SIZE = 50;// 消息池的最大数量
实际上,Message本身不单纯是一个简单的只包含数据的类,它实际上是一个链式结构的类,也就是说,一个Message本身就是一个消息队列,它通过next将所有消息串联起来。既然Message本身就是消息队列,那MessageQueue又是如何建立消息队列的又是怎么回事?实际上,MessageQueue内部只有一个Message成员,它所要做的工作就是把Message实体串连起来,形成消息链。
3.2 MessagePool消息池原理及代码分析
3.2.1 Message的构造方法
Message对象可以通过Message.obtain()或者obtainMessage()方法获得(即使Message的构造方法是公开的,也不推荐使用new创建Message);
以下列出了3种创建Message的方法:
1.new Message();
2.Message.obtain();
publicstaticMessage obtain() {
synchronized (sPoolSync) {
if (sPool != null) {
Message m = sPool;
sPool = m.next;
m.next = null;
sPoolSize--;
return m;
}
}
return new Message();
}
3.handler.obtainMessage()
Public final Message obtainMessage() {
return Message.obtain(this);
}
关于MessagePool消息池
3.2.2为什么要创建消息池
通常消息处理完毕之后,消息基本处于无用状态可以释放回收了,众所周知,频繁的创建对象与释放对象,会增加系统的开销,而Message这种对象就很有可能被频繁的创建,于是乎,有了消息池这个结构
我们将创建的对象在用完之后保存在一个Pool中,当我们下次需要使用对象时,可以不去创建对象,而是从池中取出一个对象重复利用
流程图:
图3:消息池工作流程图
3.2.3 MessagePool的建立
以下省略部分不必要的代码
Looper.class ====>>
Public static voidloop() {
.....................
msg.recycle(); // 处理完的消息调用recycle方法()
}
Message.class ====>>
Public void recycle() {
clearForRecycle();// 将所有数据清零
synchronized (sPoolSync) {
if (sPoolSize<MAX_POOL_SIZE) {
next = sPool;//结合obtain()理解更清晰
sPool = this;//该对象保存在pool中
sPoolSize++;// 池内消息数量+1
}
}
}
3.2、Looper源码解析
Looper介绍:
是MessageQueue的管理者,每一个MessageQueue都不能脱离Looper而存在,Looper对象的创建是通过prepare函数来实现的,每一个Looper对象和一个线程关联,子线程默认是没有Looper对象的,需要通过prepare函数,自己定义一个Looper对象,当创建一个Looper对象时,Looper对象会自动创建一个MessageQueue,当调用Looper.loop方法时,会启动Looper来遍历MessageQueue
每个Looper对象通过ThreadLocal.set(new Looper())跟一个Thread绑定了,Looper对象所属的线程在Looper.Loop方法中循环执行从MessageQueue队列读取Message对象,并把Message对象交由Handler处理,调用Handler的dispatchMessage方法。
MainLooper:主线程的Looper
主线程的Looper是Android系统默认给创建的,不需要手动创建, 可以通过Looper.getMainLooper()方法获取主线程的Looper对象
Looper.class代码:
3.2.1 Looper.prepare();方法解析
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread"); // 一个线程只能有一个Looper,否则报出RuntimeException
}
sThreadLocal.set(new Looper(quitAllowed));// 保存
}
下面附上ThreadLocal.set()代码
publicvoid set(T value) {
Thread currentThread = Thread.currentThread();
Values values = values(currentThread);
if (values == null) {
values = initializeValues(currentThread);
}
values.put(this, value);
}
prepare()究竟做了什么:将looper保存于一个类似于Map的结构中,key为当前线程,value为当前线程的looper对象
Looper.myLooper(),获取当线程对应的Looper对象
附上Looper.class的几个属性
static final ThreadLocal<Looper>sThreadLocal = new ThreadLocal<Looper>();
private static Looper sMainLooper;
final MessageQueue mQueue;
下面是ThreadLocal.get()的源代码
/**
*返回此变量的当前线程的值。如果一个条目
*还没有为这个线程该变量存在,此方法将
*创建一个条目,用结果填充值
*{@link#initialValue()}。
*@返回变量的调用线程的当前值。
*/
public T get() {
// Optimized for the fast path. 优化的快速路径?
Thread currentThread = Thread.currentThread();
Values values = values(currentThread);
if (values != null) {
Object[] table = values.table;
int index = hash& values.mask;
if (this.reference == table[index]) {
return (T) table[index + 1];
}else {
values = initializeValues(currentThread);
}
return (T) values.getAfterMiss(this);
}
3.3、ThrealLocal<T>
=======================================
/**
*实现一个线程局部存储,也就是一个变量,每个线程
*有其自身的值。所有线程共享相同的{@ ThreadLocal的代码}对象,
*但每次访问它时,看到一个不同的值,并且由一个所做的更改
*线程不影响其他线程。实现支持{@ null}值。
*
*@看到的java.lang.Thread
*@作者鲍勃·李
*/
=======================================
TreadLocal类在JDK5.0支持泛型,类名变为ThreadLocal<T>
ThreadLocal<T>概述
为我们解决多线程程序的并发问题提供了一种新的思路。使用这个工具类可以很简洁地编写出优美的多线程程序。
ThreadLocal其实是一个Thread的局部变量,也许把它命名ThreadLocalVariable更容易让人理解一些。当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本
ThreadLocal<T>的接口方法
ThreadLocal类接口很简单,只有4个方法,我们先来了解一下:
void set(Object value) ==> JDK5.0之后支持泛型==> void set (T value)
设置当前线程的线程局部变量的值。
public Object get() ==> JDK5.0之后 ==> public T get()
该方法返回当前线程所对应的线程局部变量
public void remove()
将当前线程局部变量的值删除,目的是为了减少内存的占用,该方法是JDK 5.0新增的方法。需要指出的
是,当线程结束后,对应该线程的局部变量将自动被垃圾回收,所以显式调用该方法清除线程的局部变量
并不是必须的操作,但它可以加快内存回收的速度
protected Object initialValue() ==> JDK5.0之后 ==> protected T initialValue()
返回该线程局部变量的初始值,该方法是一个protected 的方法,显然是为了让子类覆盖而设计的。这个方法是一个延迟调用方法,在线程第1次调用get()或set(Object)时才执行,并且仅执行1次。ThreadLocal中的缺省实现直接返回一个null
实现原理/流程图
当多个Thread对象同时去访问一个Threadlocal对象时,Threadlocal对象只是充当一个Key的角色,而不是变量的储存介质,Threadlocal对象的set()和get()方法所涉及的value是储存于ThrealocalMap中的value,而ThreadlocalMap是每个Thread各自专用的,互补相等的,这就是Threadlocal被多线程同时访问,Threadlocal的值互不干扰的原理
图4: ThreadLocal运行流程图
Thread与同步机制比较
应在线程同步机制中,通过对象的锁机制保证同一时间只有一个线程访问变量, 这时该变量是多个线程共享的,使用同步机制要求程序慎密的分析什么时候对变量进行读写,什么时候需要锁定某个对象,什么时候释放对象锁等复杂问题,程序设计和编写难度相对较大
而ThreadLocal则从另一个角度来解决多线程的并发访问,ThreadLocal会为每一个线程提供一个独立的线程拷贝,从而隔离了多个线程对数据的访问冲突,因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了,ThreadLocal提供了线程安全的共享对象,在编写多项成代码时,可以把不安全的变量封装进ThreadLocal
Threadlocal小结
ThreadLocal并不能替代同步机制,两者面向的问题领域不同。同步机制是为了同步多个线程对相同
资源的并发访问,是为了多个线程之间进行通信的有效方式;而ThreadLocal是隔离多个线程的数据共享,从根本上就不在多个线程之间共享资源(变量),这样当然不需要对多个线程进行同步了。所以,如果你需要进行多个线程之间进行通信,则使用同步机制;如果需要隔离多个线程之间的共享冲突,可以使用
ThreadLocal,这将极大地简化你的程序,使程序更加易读、简洁。
为什么要在Looper中使用ThreadLocal
好处很明显,如果用一个全局的HashMap来管理Looper的话,当需要增删改某个Looper对象时,就需要进行同步操作,这大大增加了系统开销,如果有一个ThreadlocalMap保存于本地线程里,需要用的时候直接去取,就可以避免同步带来的低效率问题,所以Threadlocal正好被应用到了一个Thread对应一个Looper中
3.4 Looper.loop();-----------启动消息循环
public static void loop() {
final Looper me = myLooper(); // 由于是静态方法,所以需要获取当前线程的Looper对象
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue; //获取当前looper对象绑定的MessageQueue对象
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity(); //该方法返回的是当前进程的pid、uid等信息混合后的唯一标示
for (;;) { //开始循环
Message msg = queue.next(); //从消息队列中获取msg
if (msg == null) {
return; //若msg为null,则结束此循环
}
Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + "" +
msg.callback + ": " + msg.what);
}
//若msg不为null,则调用msg.target.dispatchMessage()方法
msg.target.dispatchMessage(msg);
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + "" + msg.callback);
}
final long newIdent = Binder.clearCallingIdentity();//再次获取一次标示
if (ident != newIdent) {
Log.wtf(TAG, "Thread identity changed from 0x"
+ Long.toHexString(ident) + " to 0x"
+ Long.toHexString(newIdent) + " while dispatching to "
+ msg.target.getClass().getName() + ""
+ msg.callback + " what=" + msg.what);
}
msg.recycle();// MessagePool回收msg
}
}
3.5、MessageQueue.class源码分析
3.5.1 MessageQueue类的介绍:
用于管理消息链表的类,但其中并不是Java中的Queue,因为通过Message的属性next,就可以看出,Message类本身就算是一个链表结构,而MessageQueue类的作用,就是管理这个链表结构
下面附上一些MessageQueue的部分属性
Message mMessages;// Message实例,代表队列的头元素
private final ArrayList<IdleHandler> mIdleHandlers = new ArrayList<IdleHandler>();// 存放IdleHandler的ArrayList
private IdleHandler[] mPendingIdleHandlers;//是数组版本,后面的代码将把mIdleHandlers的内容拷贝到这个数组中
private boolean mQuiting;// 布尔类型值,判断队列是否在退出状态
3.5.2 IdleHandler接口解析;
IdleHandler接口的作用:
允许用户注册一个回调,当线程将要出去空闲状态时,提前给用户一个回调,用户可以利用这个空闲时间干点其他事情
public static interface IdleHandler {
boolean queueIdle();
}
//一个用于在一个线程里等待更多消息阻塞的接口,当消息队列为null时,等待更多消息,执行这个queueIdle(),如果返回真,则继续保持你的IdlieHandler的活跃状态,下次空闲时仍会再执行这个IdileHandler,如果消息队列里有消息,但是他们的执行时间在当前时间之后,queueIdle也会被调用;如果返回值为false,则remove这个IdlieHandler
添加方法:
public void addIdleHandler(IdleHandler handler) {
if (handler == null) {
throw new NullPointerException("Can't add a null IdleHandler");
}
synchronized (this) {
mIdleHandlers.add(handler);
}
}
向消息队列中添加一个新的MessageQueue.IdleHandler。当调用IdleHandler.queueIdle()返回false时,此MessageQueue.IdleHandler会自动的从消息队列中移除。
删除方法:
public void removeIdleHandler(IdleHandler handler) {
synchronized (this) {
mIdleHandlers.remove(handler);
}
}
下面附上一个IdleHandler的使用例子:
Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler() {
public boolean queueIdle() {
Log.d("Sandy", "queueIdle");
Toast.makeText(MainActivity.this, "主线程空闲了", Toast.LENGTH_SHORT).show();
return false;
}
});
3.5.3 next()方法解析;
Message next() {
int pendingIdleHandlerCount = -1; // -1 only during first iteration
int nextPollTimeoutMillis = 0;// 初始化了两个变量
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();}// native方法,,不解
nativePollOnce(mPtr, nextPollTimeoutMillis);
==================================================
//虽然这是一个native方法,但是我们方法名字和下面的代码可以看出,nativePollOnce等待完毕之后,next函数将从mMessages中获取一个Message,也就是说,要让nativePollOnce方法返回,就至少要添加一个Message到消息队列中
==================================================
synchronized (this) {
// Try to retrieve the next message. Return if found.
final long now = SystemClock.uptimeMillis();//获取当前时间
Message prevMsg = null;//初始化变量为null
Message msg = mMessages;//获取队列的消息头
if (msg != null && msg.target == null) {
do {
prevMsg = msg;//同时更新prevMsg变量
msg = msg.next;//如果队列的消息头为null,则获取下一个消息
} while (msg != null && !msg.isAsynchronous());
}//直到 msg==null(搜寻到了队列的尾部,表示没有更多的消息)或者 搜寻到一个异步消息
if (msg != null) {//如果找到了一个消息
if (now < msg.when) {
nextPollTimeoutMillis=
(int)Math.min(msg.when-now, Integer.MAX_VALUE);
//当msg到了该处理的时间,也就是说我们找到了消息,则把消息返回
} else {
// Got a message.
mBlocked = false;
//下面几行代码的大概意思是,设置mBolocked为false,将msg从mMessages队列里取出,并执行msg.next==null、msg.markInUse()操作,如果没有return的话则继续等待(else之后的操作)
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
msg.next = null;
if (false){
Log.v("MessageQueue", "Returning message: " + msg);
msg.markInUse();
return ms ; //如果获取了一个正常的Message,就会交给Looper进行处理
} else {
//nativePollOnce方法结束之后,会尝试获取 Message,如果获取不到,就将nextPollTimeoutMillis的值设置为-1,继续等待
nextPollTimeoutMillis = -1;
}
if (mQuiting) {//因为没有return,所以检查队列是否要求退出
dispose();//如果是,则执行dispose()方法
return null;
}
//下面既然没有消息要处理,则线程处于空闲状态-->>处理idlerHandler对象
==================================================
//判断mIdleHandlers(ArrayList)是否大于0,如果是就将这里的元素取出,放入mPendingIdleHandlers数组中,并迭代这个数组
==================================================
if (pendingIdleHandlerCount < 0
&& (mMessages == null || now <mMessages.when)){
pendingIdleHandlerCount = mIdleHandlers.size();
}
if (pendingIdleHandlerCount <= 0) {
// No idle handlers to run. Loop and wait some more.
mBlocked = true;
continue;
}
if (mPendingIdleHandlers == null) {
mPendingIdleHandlers=new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
}
mPendingIdleHandlers= mIdleHandlers.toArray(mPendingIdleHandlers);
}
==================================================
遍历mPendingIdleHandlers数组
==================================================
for (int i = 0; i < pendingIdleHandlerCount; i++) {
final IdleHandler idler = mPendingIdleHandlers[i];
mPendingIdleHandlers[i] = null;
boolean keep = false;
try {
keep = idler.queueIdle();//根据idler的返回值,决定是否保留这个idleHandler
} catch (Throwable t) {
Log.wtf("MessageQueue", "IdleHandler threw exception", t);
}
if (!keep) {
synchronized (this) {
mIdleHandlers.remove(idler);//根据返回值,处理idler对象
}
}
pendingIdleHandlerCount = 0;
nextPollTimeoutMillis = 0;
}
}//当线程下次调用nativePollOnce函数的时候,不设置超时时间了,因为很可能在这段时间内,已经有消息加入队列了。
==================================================
3.6 equeueMessage方法解析
消息插入队列
boolean enqueueMessage(Message msg, long when) {
如果msg正在被使用,或者msg对应的handler为空或者队列正在退出状态,均报异常
==================================================
if (msg.isInUse()) {
thrownew AndroidRuntimeException(msg + " This message is already in use.");
}
if (msg.target == null) {
thrownew AndroidRuntimeException("Message must have a target.");
}
boolean needWake;
synchronized (this) {
if (mQuiting) {//如果队列正在退出状态,就不能往里插入元素了,则抛出RuntimeException,并return false ,表示插入失败
RuntimeException e = new RuntimeException(
msg.target + " sending message to a Handler on a dead thread");
Log.w("MessageQueue", e.getMessage(), e);
returnfalse;
}
==================================================
msg.when = when;//准备工作
Message p = mMessages;//获取队列的头元素
if (p == null || when == 0 || when < p.when) {
msg.next = p;
mMessages = msg;
needWake = mBlocked;
如果队列是空的,或者when==0 或者 插入时间小于p.when,则会把消息插入消息队列的头,那么msg将成为新的队列头元素, 否则插入消息队列尾
} else {
needWake = mBlocked&& p.target == null&&msg.isAsynchronous();
Message prev;
for (;;) {
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
msg.next = p; // invariant: p == prev.next
prev.next = msg;
}
}
if (needWake) {
nativeWake(mPtr);
}
return true;
}
- Android 消息系统解析(Handler.class及相关类源码解析)
- android开发-android的消息机制(Handler)源码解析
- Android:异步消息Handler源码解析
- Android消息机制Handler源码简单解析
- android源码解析(3)--handler消息机制
- Android 源码解析Handler消息传递机制
- Android消息机制源码解析(Handler)
- Android消息机制Handler解析(源码+Demo)
- Android Handler消息机制源码解析(上)
- Android Handler消息机制源码解析(下)
- Android消息队列源码解析(Handler、Looper、Message、MessageQueue)
- Handler消息机制源码解析(一)
- Handler消息机制源码解析(二)
- Handler消息机制源码解析(三)
- Handler消息机制源码解析(四)
- Handler消息机制源码解析
- Handler消息机制源码解析
- handler消息机制源码解析
- SatelliteMenu 卫星菜单项的位置调整
- oracle基本管理(2)
- 第十二周项目3-摩托车继承自行车和机动车
- Ubuntu 12.04下安装配置Python 2.7集成开发环境Eric4
- 0702-APP-notification-service
- Android 消息系统解析(Handler.class及相关类源码解析)
- 史上最全:Android开发者必知的开发资源
- 从设计模式角度看ArcGIS Engine
- usaco 4.2.3 Job Processing
- 冒泡排序
- QT 之 QImage类
- Include设置layout_*无效解决方法
- oracle基本管理(3)
- Python3.2 实现基于KNN算法的数据分类