Android 消息机制原理 (源代码分析)
来源:互联网 发布:ubuntu磁盘空间查看 编辑:程序博客网 时间:2024/09/21 06:38
Android 消息机制原理 (源代码分析)
- 示例
- 基本工作原理
- 应用进程入口函数
- 创建主循环器
- 发送消息
- 循环获取需要处理的消息,并进行处理
- 消息对象的回收与复用
示例
在主线程运行以下代码,等待一秒后,handler.handleMessage(myMsg)
将在主线程中被执行:
Handler handler = new Handler() { @Override public void handleMessage(Message msg) { ... }}new Thread() { @Override public voide run() { Message myMsg = new Message(); handler.sendMessageDelayed(myMsg, 1000L); }}.start();
基本工作原理
每个循环器(Looper
对象)内部有一个消息队列(MessageQueue
对象),负责维护当前循环器的待处理消息(Message
对象)链表,每个待处理消息按处理时间的先后顺序链接。
Handler
对象创建时会自动关联到当前线程已经创建的循环器,每个线程最多只可以创建一个循环器,当在子线程中通过前面创建的 Handler
对象发送消息时,消息就会被添加到 Handler
对象关联的循环器内部的待处理消息链表里。
创建循环器后调用 Looper.loop()
不断轮询待处理消息链表,获取当前需要处理的消息,并处理消息,Android 环境在应用启动时已经在主线程执行了这些步骤。
应用进程入口函数
AOSP:
应用进程启动时,进程入口函数 ActivityThread.main(...)
在主线程 (又称 UI 线程) 中被执行:
// AOSP(Android Open Source Project) 源代码所在文件: frameworks/base/core/java/android/app/ActivityThread.javapublic static void main(String[] args) { ... // 创建主循环器 Looper.prepareMainLooper(); ... // 不断循环阻塞等待获取需要处理的消息,并进行处理 Looper.loop(); ...}
创建主循环器
Looper.prepareMainLooper()
主要负责创建在当前线程(即主线程)创建一个循环器,作为应用的主循环器:
// AOSP: frameworks/base/core/java/android/os/Looper.java// 用于存放在不同线程中创建的循环器static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();// 主循环器private static Looper sMainLooper;// 在当前线程创建一个循环器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));}// 获取在当前线程创建的循环器public static @Nullable Looper myLooper() { return sThreadLocal.get();}public static void prepareMainLooper() { prepare(false); synchronized (Looper.class) { if (sMainLooper != null) { throw new IllegalStateException("The main Looper has already been prepared."); } sMainLooper = myLooper(); }}
初始化循环器,在内部创建一个消息队列:
// AOSP: frameworks/base/core/java/android/os/Looper.javafinal MessageQueue mQueue;final Thread mThread;private Looper(boolean quitAllowed) { // 创建消息队列 mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread();}
发送消息
初始化 Handler
对象,引用在当前线程创建的循环器,和它内部的消息队列:
// AOSP: frameworks/base/core/java/android/os/Handler.javafinal Looper mLooper;final MessageQueue mQueue;final Callback mCallback;final boolean mAsynchronous;public Handler() { this(null, false);}public Handler(Callback callback, boolean async) { ... // 引用在当前线程创建的循环器,如果是主线程将引用主循环器 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;}
Handler.post...(...)
、Handler.send...(...)
、Handler.sendMessageAtFrontOfQueue(...)
都是负责发送消息,它们最终调用 Handler.enqueueMessage(...)
将消息交给初始化时关联的消息队列:
// AOSP: frameworks/base/core/java/android/os/Handler.javapublic boolean sendMessageAtTime(Message msg, long uptimeMillis) { MessageQueue queue = mQueue; if (queue == null) { ... return false; } return enqueueMessage(queue, msg, uptimeMillis);}public final boolean sendMessageAtFrontOfQueue(Message msg) { MessageQueue queue = mQueue; if (queue == null) { ... return false; } return enqueueMessage(queue, msg, 0);}private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { // 负责处理消息的 Handler 对象 msg.target = this; if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis);}
MessageQueue.enqueueMessage(...)
将消息插入到有序的待处理消息链表中:
// AOSP: frameworks/base/core/java/android/os/MessageQueue.java// 待处理消息链表头Message mMessages;// 保存到链表时,指向下一个消息对象Message next;boolean enqueueMessage(Message msg, long when) { if (msg.target == null) { throw new IllegalArgumentException("Message must have a target."); } if (msg.isInUse()) { throw new IllegalStateException(msg + " This message is already in use."); } synchronized (this) { ... msg.markInUse(); msg.when = when; Message p = mMessages; ... // 如果 when 为 0 插入到链表头,否则按 when 属性从小到大插入到链表, // 如果遇到相同,再按从先进到后进插入到链表 if (p == null || when == 0 || when < p.when) { msg.next = p; mMessages = msg; ... } else { ... Message prev; for (;;) { prev = p; p = p.next; if (p == null || when < p.when) { break; } ... } msg.next = p; // invariant: p == prev.next prev.next = msg; } ... } return true;}
循环获取需要处理的消息,并进行处理
Looper.loop()
负责不断循环调用 MessageQueue.next()
获取需要处理的消息,并调用 Handler.dispatchMessage(...)
处理消息:
// AOSP: frameworks/base/core/java/android/os/Looper.javapublic 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; ... for (;;) { // 获取当前需要处理的消息 Message msg = queue.next(); if (msg == null) { // No message indicates that the message queue is quitting. return; } ... // 处理消息 msg.target.dispatchMessage(msg); ... // 回收消息对象 msg.recycleUnchecked(); }}
MessageQueue.next()
阻塞等待,返回待处理消息链表中靠前那个当前需要处理的消息:
// AOSP: frameworks/base/core/java/android/os/MessageQueue.javaMessage next() { ... int nextPollTimeoutMillis = 0; for (;;) { ... // TODO: 有待继续分析 // 进程挂起 nextPollTimeoutMillis 毫秒,若链表发生变化则提前唤醒(见底层 epoll 函数) nativePollOnce(ptr, nextPollTimeoutMillis); synchronized (this) { // 获取自开机以来经过的毫秒数 final long now = SystemClock.uptimeMillis(); Message prevMsg = null; Message msg = mMessages; if (msg != null && msg.target == null) { // TODO: 有待继续分析 // 跳过障碍,寻找下一个异步消息 do { prevMsg = msg; msg = msg.next; } while (msg != null && !msg.isAsynchronous()); } if (msg != null) { if (now < msg.when) { // 计算这个消息需要等待的时间 nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE); } else { // 时间已到,将消息从待处理消息链表删除并返回 mBlocked = false; if (prevMsg != null) { prevMsg.next = msg.next; } else { mMessages = msg.next; } msg.next = null; ... msg.markInUse(); return msg; } } else { nextPollTimeoutMillis = -1; } ... } ... }}
Handler.dispatchMessage(...)
处理消息:
// AOSP: frameworks/base/core/java/android/os/Handler.java// 子类需覆盖本方法用来接收消息public void handleMessage(Message msg) {}public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); }}
消息对象的回收与复用
Message.recycleUnchecked()
负责将自己放入缓存池留待复用:
// AOSP: frameworks/base/core/java/android/os/Message.javaprivate static final Object sPoolSync = new Object();// 共享缓存池的链表头private static Message sPool;// 当前共享缓存池大小private static int sPoolSize = 0;// 共享缓存池大小上限private static final int MAX_POOL_SIZE = 50;// 保存到链表时,指向下一个消息对象Message next;void recycleUnchecked() { // 清除所有属性 flags = FLAG_IN_USE; what = 0; arg1 = 0; arg2 = 0; obj = null; replyTo = null; sendingUid = -1; when = 0; target = null; callback = null; data = null; synchronized (sPoolSync) { // 缓存池大小未达到上限,将自己插入到缓存池的链表头 if (sPoolSize < MAX_POOL_SIZE) { next = sPool; sPool = this; sPoolSize++; } }}
Message.obtain(...)
最终都是调用 Message.obtain()
创建消息对象,它先尝试从共享缓存池返回一个空闲的消息对象,如果没有再去创建:
// AOSP: frameworks/base/core/java/android/os/Message.javapublic static Message obtain() { synchronized (sPoolSync) { // 共享缓存池不为空,弹出链表头的消息对象 if (sPool != null) { Message m = sPool; sPool = m.next; m.next = null; m.flags = 0; // clear in-use flag sPoolSize--; return m; } } // 共享缓存池为空,创建新的消息对象 return new Message();}
Handler.post...(...)
和 Handler.send...(...)
类函数族,如果参数列表中未带 Message
类型参数,内部实现使用 Message.obtain(...)
创建消息对象。
- Android 消息机制原理 (源代码分析)
- android 消息机制 Handler Looper 原理分析
- 消息机制原理分析
- [Android源代码分析]Android消息机制,Handler,Message,Looper,MessageQueue
- Lenix消息机制源代码分析
- Android 消息机制--Handler机制(二)四大原理分析
- 【Android】消息机制原理
- Android消息机制分析
- Android消息机制分析
- Android--Handler使用应运及消息机制处理原理分析
- Android消息机制(Handler原理)
- Android 消息处理机制原理
- Android消息机制底层原理
- android消息机制原理详解
- Android 消息机制原理解析
- Android消息机制底层原理
- android消息机制源码分析
- Android 消息机制源码分析
- C语言代码书写风格
- vue刷新数据
- 闭包的认识
- 对于跨域总是not call back 的问题
- 动态表格的增删改查
- Android 消息机制原理 (源代码分析)
- Oracle 11gR2中针对备份恢复功能的增强
- LCD设备驱动(二)
- 1、初识scrapy
- 数据事务四种隔离机制和七种传播行为
- mysql的事务的隔离级别
- MyBatis用嵌套ResultMap实现一对多映射
- linux 的重定向、管道、xargs 命令
- DI【理解】【应用】【重点】