Android:异步消息源码解析
2015-07-31 11:58
302 查看
关于异步消息的用法,可以看之前的一篇文章/article/1904021.html,现在来解析一下源码。
如此一来,我们便可以在其他线程,通过handler来发送消息给当前线程,达到异步效果。
这个方法辗转调用了下列的方法:
prepare方法给ThreadLocal对象set了一个Looper对象,由抛出的异常可以看出每个线程只能有一个Looper对象,那么这个Looper又是用来干嘛的呢?
Looper绑定了当前线程和MessageQueue。
2、
实例化了Handler对象,后面再回来分析这个Handler对象的作用
3、
第2、6行可以看到,这个方法获取了Looper对象和主要的
很明显,就是将消息分发给处理者。而这里的msg.target正是Handler对象。
我们来分别看下这三个可能,也都是常用情景:
①handler对象post一个任务
继续调用
可以看到handler post进去的任务会赋给message后才进行MessageQueue入队,最终Handler处理这个Message时就会调用这个任务。
②实例化Handler对象时传进一个Callback对象
最终就会回调这个handleMessage方法。
③最常见的情景,实例化时重写handleMessage(msg)方法,这也是上面消息分发的最后一种可能。
最后两个小问题,
1、Message的MessageQueue入队操作是由Handler对象进行,入队时就会把target设为当前操作的Handler,这样处理消息时就能找到合适的Handler了!
2、主线程的Looper是由系统生成的,找了半天源码没找见,但是官方文档说的很清楚
Looper对象负责创建MessageQueue对象,并且不断从MessageQueue取出Message,一旦取出则分发消息,最终都会直接或间接被Handler处理。
研究AsyncTask源码可以发现,内部是对Handler的封装;
实现子线程发送消息给主线程很常见,试下向子线程发送消息,会更加明了。
经典用法
[code]class LooperThread extends Thread { public Handler mHandler; public void run() { Looper.prepare(); mHandler = new Handler() { public void handleMessage(Message msg) { // process incoming messages here } }; Looper.loop(); } }
如此一来,我们便可以在其他线程,通过handler来发送消息给当前线程,达到异步效果。
流程
1、Looper.prepare();
这个方法辗转调用了下列的方法:
[code] 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"); } sThreadLocal.set(new Looper(quitAllowed)); }
prepare方法给ThreadLocal对象set了一个Looper对象,由抛出的异常可以看出每个线程只能有一个Looper对象,那么这个Looper又是用来干嘛的呢?
[code] private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); }
Looper绑定了当前线程和MessageQueue。
2、
mHandler = new Handler() {...};
实例化了Handler对象,后面再回来分析这个Handler对象的作用
3、
Looper.loop();
[code] public static void loop() { final Looper me = myLooper(); if (me == null) { throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); } final MessageQueue queue = me.mQueue; // Make sure the identity of this thread is that of the local process, // and keep track of what that identity token actually is. Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity(); for (;;) { Message msg = queue.next(); // might block if (msg == null) { // No message indicates that the message queue is quitting. return; } // This must be in a local variable, in case a UI event sets the logger Printer logging = me.mLogging; if (logging != null) { logging.println(">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what); } msg.target.dispatchMessage(msg); if (logging != null) { logging.println("<<<<< Finished to " + msg.target + " " + msg.callback); } // Make sure that during the course of dispatching the // identity of the thread wasn't corrupted. 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.recycleUnchecked(); } }
第2、6行可以看到,这个方法获取了Looper对象和主要的
MessageQueue对象,重点看13、14行,方法内部是一个死循环,不断从MessageQueue里面拉取Message,并且是阻塞式的,也就是说拉不到Message就停在那里了。假设拉到了Message,则调用第27行
[code]msg.target.dispatchMessage(msg);
很明显,就是将消息分发给处理者。而这里的msg.target正是Handler对象。
[code] public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } }
我们来分别看下这三个可能,也都是常用情景:
①handler对象post一个任务
[code] handler.post(new Runnable() { @Override public void run() { } });
继续调用
[code] public final boolean post(Runnable r) { return sendMessageDelayed(getPostMessage(r), 0); } private static Message getPostMessage(Runnable r) { Message m = Message.obtain(); m.callback = r; return m; }
可以看到handler post进去的任务会赋给message后才进行MessageQueue入队,最终Handler处理这个Message时就会调用这个任务。
②实例化Handler对象时传进一个Callback对象
[code]Handler handler = new Handler(new Handler.Callback() { @Override public boolean handleMessage(Message msg) { return false; } });
[code]if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } }
最终就会回调这个handleMessage方法。
③最常见的情景,实例化时重写handleMessage(msg)方法,这也是上面消息分发的最后一种可能。
最后两个小问题,
1、Message的MessageQueue入队操作是由Handler对象进行,入队时就会把target设为当前操作的Handler,这样处理消息时就能找到合适的Handler了!
2、主线程的Looper是由系统生成的,找了半天源码没找见,但是官方文档说的很清楚
The main looper for your application is created by the Android environment
小结
Handler对象负责将Message传入MessageQueue,而MessageQueue由Looper对象生成;Looper对象负责创建MessageQueue对象,并且不断从MessageQueue取出Message,一旦取出则分发消息,最终都会直接或间接被Handler处理。
研究AsyncTask源码可以发现,内部是对Handler的封装;
实现子线程发送消息给主线程很常见,试下向子线程发送消息,会更加明了。
相关文章推荐
- Android之常用类型转换
- Android ListView相关功能介绍
- android 实现progressdialog 等待界面
- android.content.res.Resources$NotFoundException:+String+resource+ID+#0x1
- android 定制自己的log工具类
- Android 的manifest解析
- 从零开始学习android,记录他人的博客
- android-友盟第三方登录,及分享的使用
- 说说Android应用的persistent属性
- Android NDK *** could not be resolved
- android studion Gradle多渠道打包
- 图解Android应用程序构建原理
- Android开发笔记---service的简单使用
- Android-倒计时工具类
- Android端与Java服务端交互——SocketIO
- 解读Android虚拟机工作原理
- android studio Gradle基础
- 深入分析Android系统中SparseArray的源码
- android开源框架(开始开发的时候参考)
- Android性能优化之一:ViewStub