Android消息机制之Handler的深入理解
2017-10-15 22:58
465 查看
上周老大让我主持了一个团队技术培训的会议,会议的内容是Handler技术的整体使用流程,包括从Java端到Native端的分析。借此机会,写成一篇文章记录一下成果。若有不足之处,希望大家可以指出,欢迎互相讨论,谢谢。
Java层中的消息生成是从用户创建的Message对象而来的,它是一个由Runnable封装过的对象。或者从Message Pool调用getsMessage派生得来的,而Message Pool是指消息类Message循环队列,这个队列可以容纳的最大Message数量是MAX_POOL_SIZE=50。
![](http://img.blog.csdn.net/20171015214726985?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveHoxMDU2MQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
既然说到了Message,那么就有必要提一下Looper,Handler,MessageQuene和Message之间的关系了。
![](http://img.blog.csdn.net/20171015214953163?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveHoxMDU2MQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
总结如下:
一个Thread仅对应一个Looper;而一个Looper对象只对应一个MessageQueue;另外,一个MessageQueue对应多个Messsage;一个Message只对应一个Handler
所以我们得出的结论是:一个Thread可以对应多个Handler
MessagePool是一个循环队列,当Message的数量超过50个的时候,则会回到队头并请空该Message,为了下一次复用。
BlockingRunnable是在“包装器”构造函数中传递的Runnable 的任务,而对BlockingRunnable的postAndWait调用执行以下操作:
锁定交付BlockingRunnable的线程
如果交付BlockingRunnable失败,则返回false
主要完成的任务:
获取当前的Handler类
如果声明的程序是匿名内部类,成员类或局部类,并且处理程序的修饰符不是静态的。那么会打印出日志,提示可能会发生内存泄漏。
参数介绍:
sMainLooper:Looper使用主线程
mQueue:与Looper关联的MessageQueue
mThread:与Looper关联的线程
sThreadLocal:线程局部变量key
由此我们可以看到一个线程对应一个Looper,一个Looper对应一个MessageQueue
在为其他线程创建Looper后,调用loop()将执行以下操作:
在MessageQueue中循环获取消息
将消息通过Handler的dispatchMessage方法分配给相应的Handler
清空消息,并将其回收到Message Pool中供下次使用
在Handler的dispatchMessage中:
如果Message设置了回调,则将Message传递给Message的回调处理
如果Handler设置了回调,则将Message先交给Handler的回调方法处理。否则,将消息交给Handler的handleMessage处理。
Java层中的消息生成是从用户创建的Message对象而来的,它是一个由Runnable封装过的对象。或者从Message Pool调用getsMessage派生得来的,而Message Pool是指消息类Message循环队列,这个队列可以容纳的最大Message数量是MAX_POOL_SIZE=50。
既然说到了Message,那么就有必要提一下Looper,Handler,MessageQuene和Message之间的关系了。
总结如下:
一个Thread仅对应一个Looper;而一个Looper对象只对应一个MessageQueue;另外,一个MessageQueue对应多个Messsage;一个Message只对应一个Handler
所以我们得出的结论是:一个Thread可以对应多个Handler
MessagePool是一个循环队列,当Message的数量超过50个的时候,则会回到队头并请空该Message,为了下一次复用。
BlockingRunnable
先上代码:private static final class BlockingRunnable implements Runnable { private final Runnable mTask; private boolean mDone; public BlockingRunnable(Runnable task) { mTask = task; } @Override public void run() { try { mTask.run(); } finally { synchronized (this) { mDone = true; notifyAll(); } } } public boolean postAndWait(Handler handler, long timeout) { if (!handler.post(this)) { return false; } synchronized (this) { if (timeout > 0) { final long expirationTime = SystemClock.uptimeMillis() + timeout; while (!mDone) { long delay = expirationTime - SystemClock.uptimeMillis(); if (delay <= 0) { return false; // timeout } try { wait(delay); } catch (InterruptedException ex) { } } } else { while (!mDone) { try { wait(); } catch (InterruptedException ex) { } } } } return true; } }
BlockingRunnable是在“包装器”构造函数中传递的Runnable 的任务,而对BlockingRunnable的postAndWait调用执行以下操作:
锁定交付BlockingRunnable的线程
如果交付BlockingRunnable失败,则返回false
消息传递和处理
获取消息后,会通过Handler中sendMessageAtTime方法调用MessageQueue的enqueueMessage,并将消息传递给MessageQueue。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()); } } mLooper = Looper.myLooper(); if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; mCallback = callback; mAsynchronous = async; } public static @Nullable Looper myLooper() { return sThreadLocal.get(); }
主要完成的任务:
获取当前的Handler类
如果声明的程序是匿名内部类,成员类或局部类,并且处理程序的修饰符不是静态的。那么会打印出日志,提示可能会发生内存泄漏。
Looper
private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); } 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)); }
参数介绍:
sMainLooper:Looper使用主线程
mQueue:与Looper关联的MessageQueue
mThread:与Looper关联的线程
sThreadLocal:线程局部变量key
由此我们可以看到一个线程对应一个Looper,一个Looper对应一个MessageQueue
消息的分发
public static void loop() { …… for (;;) { Message msg = queue.next(); // might block …… try { msg.target.dispatchMessage(msg); } finally { …… } …… msg.recycleUnchecked(); } }
public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } }
在为其他线程创建Looper后,调用loop()将执行以下操作:
在MessageQueue中循环获取消息
将消息通过Handler的dispatchMessage方法分配给相应的Handler
清空消息,并将其回收到Message Pool中供下次使用
在Handler的dispatchMessage中:
如果Message设置了回调,则将Message传递给Message的回调处理
如果Handler设置了回调,则将Message先交给Handler的回调方法处理。否则,将消息交给Handler的handleMessage处理。
相关文章推荐
- Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系
- Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系
- Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系
- Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系
- Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系
- Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系
- Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系
- Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系
- Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系
- 深入理解Android消息机制,从源码解析Handler,Looper,MessageQueue
- Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系
- Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系
- Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系
- Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系
- Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系
- Android 异步消息处理机制 深入理解 Looper、Handler、Message
- Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系
- Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系
- Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系【转】
- Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系