android异步消息机制,Handler,Looper,MessageQueue的关系
来源:互联网 发布:彩影软件怎么样 编辑:程序博客网 时间:2024/05/17 03:41
前言:
参考了鸿洋_大神的这篇文章:http://blog.csdn.net/lmj623565791/article/details/38377229
(1)在android中线程间的消息通信是通过handler实现的。handler的常见应用:因为在android中对UI操作只能在主线程中操作,而一些耗时的操作又不能在主线程进行,所以会在子线程做一些网络请求等的耗时操作,然后通过handler把子线程的任务切换到主线程中,在主线程中进行UI操作。如下代码:
private Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); new Thread(new Runnable() { @Override public void run() { Message message = Message.obtain(); message.what = 1; handler.sendMessage(message); } }).start(); }
(2)handler的运行其实需要looper和messageQueue支持,只是当新建Activity已经帮我们新建了looper和messageQueue。如果在子线程使用handler,必须调用Looper.prepare和Looper.loop。如下代码:
class MyThread implements Runnable{ private Handler handler; @Override public void run() { Looper.prepare(); handler = new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); } }; Looper.loop(); } }
(3)handler的应用流程。首先通过Looper.prepare(),将Looper绑定到当前线程,创建Looper实例时会创建一个MessageQueue。当新建一个Handler实例时会获取到当前的线程的Looper和MessageQUeue。当通过handler.sendMessage(message)方法时会把Message插入到MessageQueue中。最后通过Looper.loop()不停遍历MessageQueue,得到Message,并交给msg.target处理,target就是当前handler(handle赋值给msg.target是在handler.sendMessage(message)中实现的)。target会调用msg.target.dispatchMessage(msg)处理,dispatchMessage最后会调用 handleMessage(msg)处理message。handleMessage也是我们需要重写的方法。下面将下各方法的实现原理。
1.Looper.prepare()
Looper.prepare()的作用是创建一个Looper并绑定到当前线程,同时创建一个MessageQueue。Looper绑定到当前线程通过ThreadLocal实现的。
ThreadLocal的作用:为不同线程互不干扰的存储和提供数据(具体原理可以看下singwhatiwanna大神的这篇文章点击打开链接)。
在代码的78行sThreadLocal.set(new Looper(quitAllowed)),新建了一个Looper实例存储到了ThreadLocal中,并在这之前判定了ThreadLocal之前是否存储了Looper,不为null则抛出异常,这样保证了一个线程只有一个Looper。
51 52 public final class More ...Looper {53 private static final String TAG = "Looper";54 55 // sThreadLocal.get() will return null unless you've called prepare().56 static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();57 private static Looper sMainLooper; // guarded by Looper.class58 59 final MessageQueue mQueue;60 final Thread mThread;61 62 private Printer mLogging;
</pre><pre name="code" class="html"></pre><pre name="code" class="html">70 public static void More ...prepare() {71 prepare(true);72 }73
74 private static void More ...prepare(boolean quitAllowed) {75 if (sThreadLocal.get() != null) {76 throw new RuntimeException("Only one Looper may be created per thread");77 }78 sThreadLocal.set(new Looper(quitAllowed));79 }
下面看下Looper的构造方法。在新建Looper会创建一个MessageQueue。一个就实现了一个线程只有一个Looper和MessageQueue。
private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mRun = true; mThread = Thread.currentThread();}
2.新建一个Handler对象。
Handler的构造方法的第198行mLooper = Looper.myLooper()获取了当前线程的Looper。再看下Looper.myLooper()的实现,其实是获取了LocalThread存储的Looper, return sThreadLocal.get()第161行,就是在代码78行保存的Looper。
mQueue = mLooper.mQueue(203行)获取了MessageQueu。这样通过新建一个Handler对象,通过ThreadLocal使Handler和Looper,MessageQueue联系到一起。
187188 public More ...Handler(Callback callback, boolean async) {189 if (FIND_POTENTIAL_LEAKS) {190 final Class<? extends Handler> klass = getClass();191 if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&192 (klass.getModifiers() & Modifier.STATIC) == 0) {193 Log.w(TAG, "The following Handler class should be static or leaks might occur: " +194 klass.getCanonicalName());195 }196 }197198 mLooper = Looper.myLooper();199 if (mLooper == null) {200 throw new RuntimeException(201 "Can't create handler inside thread that has not called Looper.prepare()");202 }203 mQueue = mLooper.mQueue;204 mCallback = callback;205 mAsynchronous = async;206 }
160 public static Looper More ...myLooper() {161 return sThreadLocal.get();162 }
先看下代码。不管是sendMessage还是sendEmptyMessage最后都是调用enqueueMessage(626行开始).我们看下enqueueMessage方法实现。queue.enqueueMessage(msg, uptimeMillis)(631行)把message加入到了MessageQueue中。msg.target = this(627行),把当前Handler赋值给了msg.taget。当Looper遍历MessageQueue,取出Message会交给msg.taget处理,也就是交给handler处理了。
505 public final boolean More ...sendMessage(Message msg)506 {507 return sendMessageDelayed(msg, 0);508 }
516517 public final boolean More ...sendEmptyMessage(int what)518 {519 return sendEmptyMessageDelayed(what, 0);520 }
531 public final boolean More ...sendEmptyMessageDelayed(int what, long delayMillis) {532 Message msg = Message.obtain();533 msg.what = what;534 return sendMessageDelayed(msg, delayMillis);535 }
592 public boolean More ...sendMessageAtTime(Message msg, long uptimeMillis) {593 MessageQueue queue = mQueue;594 if (queue == null) {595 RuntimeException e = new RuntimeException(596 this + " sendMessageAtTime() called with no mQueue");597 Log.w("Looper", e.getMessage(), e);598 return false;599 }600 return enqueueMessage(queue, msg, uptimeMillis);601 }
626 private boolean More ...enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {627 msg.target = this;628 if (mAsynchronous) {629 msg.setAsynchronous(true);630 }631 return queue.enqueueMessage(msg, uptimeMillis);632 }
当MessageQueue有消息时,会遍历MessageQueue,获取到Message,然后交给Handler处理。MessageQueue没有消息时则处于阻塞状态。
public static void More ...loop() {110 final Looper me = myLooper();111 if (me == null) {112 throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");113 }114 final MessageQueue queue = me.mQueue;115116 // Make sure the identity of this thread is that of the local process,117 // and keep track of what that identity token actually is.118 Binder.clearCallingIdentity();119 final long ident = Binder.clearCallingIdentity();120121 for (;;) {122 Message msg = queue.next(); // might block123 if (msg == null) {124 // No message indicates that the message queue is quitting.125 return;126 }127128 // This must be in a local variable, in case a UI event sets the logger129 Printer logging = me.mLogging;130 if (logging != null) {131 logging.println(">>>>> Dispatching to " + msg.target + " " +132 msg.callback + ": " + msg.what);133 }134135 msg.target.dispatchMessage(msg);136137 if (logging != null) {138 logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);139 }140141 // Make sure that during the course of dispatching the142 // identity of the thread wasn't corrupted.143 final long newIdent = Binder.clearCallingIdentity();144 if (ident != newIdent) {145 Log.wtf(TAG, "Thread identity changed from 0x"146 + Long.toHexString(ident) + " to 0x"147 + Long.toHexString(newIdent) + " while dispatching to "148 + msg.target.getClass().getName() + " "149 + msg.callback + " what=" + msg.what);150 }151152 msg.recycleUnchecked();153 }154 }
在代码110到114行获取了Looper和MessageQueue,如果Looper为空则会抛出异常。
代码121到153无限便利MessageQueue.
代码122行(Message msg = queue.next();)获取到了Message,如果没有则处于阻塞状态。
代码135行(msg.target.dispatchMessage(msg);)msg交给了msg.target处理,target就是在新建Handler实例时赋值给它的当前Handler。这里把msg交给了handler.dispatchMessage(msg)处理,我们看下dispatchMessage的代码。
</pre><pre name="code" class="html">93 public void More ...dispatchMessage(Message msg) {94 if (msg.callback != null) {95 handleCallback(msg);96 } else {97 if (mCallback != null) {98 if (mCallback.handleMessage(msg)) {99 return;100 }101 }102 handleMessage(msg);103 }104 }
在dispatchMessage方法中如果msg.callback和mCallback为null则交给102行(handleMessage(msg);)处理,handlerMessage就是我们需要重写,去处理返回的消息。
如果msg.callback不为null,看下95行handleCallback(msg),该方法实现739行(message.callback.run()),其实callback就是一个Runnable。我们在handler.post(runnable)设置了callback。
private static void More ...handleCallback(Message message) {739 message.callback.run();740 }741
324 public final boolean More ...post(Runnable r)325 {326 return sendMessageDelayed(getPostMessage(r), 0);327 }
725 private static Message More ...getPostMessage(Runnable r) {726 Message m = Message.obtain();727 m.callback = r;728 return m;729 }730
- android异步消息机制,Handler,Looper,MessageQueue的关系
- Android 异步消息机制(Looper、Handler、MessageQueue、Message关系)
- 深入理解Looper、MessageQueue、Handler之间的关系,Android的异步消息机制
- Android异步消息处理机制,详细理解Handler,Looper,Messagequeue三者的关系
- Android异步消息机制-深入理解Handler、Looper和MessageQueue之间的关系
- android的消息机制 handler looper MessageQueue 关系详解
- Android消息异步机制(ThreadLocal、MessageQueue、Looper、Handler关系总结)
- 解析 Android 异步消息机制,深入了解 Handler、Looper、MessageQueue 关系
- Android 异步消息处理机制 让你深入理解 Looper、Handler、MessageQueue、Message四者关系
- android异步消息处理机制 handler MessageQueue Looper 类 学习
- Android 源码(6) --- 异步消息机制Handler、Looper、MessageQueue
- android 消息机制,handler机制,messageQueue,looper
- Android异步消息处理 Handler Looper MessageQueue
- 深入Android的消息机制源码详解~Handler,MessageQueue与Looper关系
- android Handler Looper,MessageQueue消息机制原理
- Android消息机制 Handler,Looper,MessageQueue
- Android消息机制:Looper、Handler、MessageQueue分析
- Android 消息机制---Handler,Looper,MessageQueue,ThreadLocal
- zookeeper学习(高级特性)
- 链表的部分翻转
- 三角形
- masonry 瀑布流布局滑动到底部加载更多
- global与$GLOBALS['']的区别及用法
- android异步消息机制,Handler,Looper,MessageQueue的关系
- matlab_loglogplot
- 通过Spring @PostConstruct 和 @PreDestroy 方法 实现初始化和销毁bean之前进行的操作
- Android 添加Library Dependencies(库依赖)的方法
- 【腾讯优测干货分享】腾讯优测自研自动化测试框架经验总结与分享
- Redis中PipeLine使用
- Python:条件和循环
- WebStorm 12 2016.2.1 汉化中文版
- Ubuntu终端常用的快捷键