android Looper、Handler和MessageQueue关系
16lz
2021-01-23
android 消息框架可以在线程间传递消息,android中最广泛的应用场景就是子线程向UI线程发送更新UI的消息。 Looper:用来进行消息循环,不停的从MessageQueue中取消息。
Handler:向MessageQueue发送消息,并处理Looper传递来的消息。
Message:消息载体。 MessageQueue:消息队列的持有者,消息并不是直接存放到MessageQueue。 这是一个比较典型的应用事例。
下面我们围绕这个事例分析一下: 线程首先调用了 Looper.prepare()方法,prepare()内部调用了带有参数的prepare(boolean)方法,参数主要是控制消息队列的特殊情况(队列中无消息时该如何处理); 参数为true且 无消息时 ,退出消息队列;参数为false且无消息时,消息队列进入阻塞状态,仅当消息队列有消息时,消息队列会被唤醒。 其中sThreadLocal变量是ThreadLocal类型,ThreadLocal主要功能是保存线程本地变量;它类似于HashMap,以键值对的方式存储,键为当前线程。想详细了解的话可以看看这篇博文 http://www.cnblogs.com/dolphin0520/p/3920407.html
那么消息时如何传递到相应的Handler呢? 当我们调用Handler.sendMessage(Message)时,Message对象会保存Handler对象到target中;处理信息时调用target的dispathMessage()方法,最终会执行Handler的handleMessage()方法。
那么消息时如何传递到相应的Handler呢? 当我们调用Handler.sendMessage(Message)时,Message对象会保存Handler对象到自身,当要处理信息时,便从自身取出Handler
Handler:向MessageQueue发送消息,并处理Looper传递来的消息。
Message:消息载体。 MessageQueue:消息队列的持有者,消息并不是直接存放到MessageQueue。 这是一个比较典型的应用事例。
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(); } }
下面我们围绕这个事例分析一下: 线程首先调用了 Looper.prepare()方法,prepare()内部调用了带有参数的prepare(boolean)方法,参数主要是控制消息队列的特殊情况(队列中无消息时该如何处理); 参数为true且 无消息时 ,退出消息队列;参数为false且无消息时,消息队列进入阻塞状态,仅当消息队列有消息时,消息队列会被唤醒。 其中sThreadLocal变量是ThreadLocal类型,ThreadLocal主要功能是保存线程本地变量;它类似于HashMap,以键值对的方式存储,键为当前线程。想详细了解的话可以看看这篇博文 http://www.cnblogs.com/dolphin0520/p/3920407.html
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)); }
从上方法得出,一个线程只允许创建一个Looper,Looper创建完毕后就可以从MessageQueue取消息了;Looper.loop()后就进入消息循环了。 下面的方法主要是从消息队列取消息,然后处理消息;消息的最终消费者是Handler。 public static void loop() { final Looper me = myLooper(); if (me == null) { //没有创建Looper 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(); // 可能会阻塞 if (msg == null) { //没有消息时,表示消息队列正准备退出 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(); } }
那么消息时如何传递到相应的Handler呢? 当我们调用Handler.sendMessage(Message)时,Message对象会保存Handler对象到target中;处理信息时调用target的dispathMessage()方法,最终会执行Handler的handleMessage()方法。
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { msg.target = this; if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis); }
那么消息时如何传递到相应的Handler呢? 当我们调用Handler.sendMessage(Message)时,Message对象会保存Handler对象到自身,当要处理信息时,便从自身取出Handler
更多相关文章
- Android 的线程和线程池
- (4.1.21.4)Android Handler 异步消息处理机制的妙用 创建强大的图
- android的消息处理机制(图+源码分析)——Looper,Handler,Message (
- Android Push Notificatioin Service(Android消息推送)
- Android——消息机制中的Message Pool是个什么鬼,Message Pool会
- 解析 ViewTreeObserver 源码,体会观察者模式、Android消息传递(下)
- Android 开发艺术探索笔记(十五) 之 Android 的线程和线程池