的声明:
ActivityThread 管理应用进程中主线程的执行,根据AMS调度执行广播和其他操作
Handler 发送消息并处理消息
MessageQueue 用于存放消息的消息队列
Looper 循环消息队列中的消息循环器
Message 可在整个app中传递的消息
ActivityThreadpublic static void main(String[] args) {Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");// Install selective syscall interceptionAndroidOs.install();// CloseGuard defaults to true and can be quite spammy.  We// disable it here, but selectively enable it later (via// StrictMode) on debug builds, but using DropBox, not logs.CloseGuard.setEnabled(false);Environment.initForCurrentUser();// Make sure TrustedCertificateStore looks in the right place for CA certificatesfinal File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());TrustedCertificateStore.setDefaultUserDirectory(configDir);// Call per-process mainline module initialization.initializeMainlineModules();Process.setArgV0("<pre-initialized>");/*** 初始化Looper消息循环器,且初始化MessageQueue消息队列* prepare(false) false说明不可以移除消息队列中的所有消息* mQueue = new MessageQueue(quitAllowed);* mThread = Thread.currentThread()*/Looper.prepareMainLooper();// Find the value for {@link #PROC_START_SEQ_IDENT} if provided on the command line.// It will be in the format "seq=114"long startSeq = 0;if (args != null) {for (int i = args.length - 1; i >= 0; --i) {if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) {startSeq = Long.parseLong(args[i].substring(PROC_START_SEQ_IDENT.length()));}}}/*** 初始化ActivityThread 绑定一些类 比如:Instrumentation等等* ....* 通过AMS发送绑定Application的请求完成Application的创建* 注意:在创建Application之前会先去判断应用内是否存在ContentProvider的注册并启动它* 故:ContentProvider中的onCreate会比Application中的onCreate要先执行的原因*/ActivityThread thread = new ActivityThread();thread.attach(false, startSeq);if (sMainThreadHandler == null) {sMainThreadHandler = thread.getHandler();}if (false) {Looper.myLooper().setMessageLogging(newLogPrinter(Log.DEBUG, "ActivityThread"));}/*** 启动消息循环启 如果启动失败直接退出*/// End of event ActivityThreadMain.Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);Looper.loop();throw new RuntimeException("Main thread loop unexpectedly exited");}
Looperpublic static void prepareMainLooper() {// 准备一个Looperprepare(false);synchronized (Looper.class) {if (sMainLooper != null) {throw new IllegalStateException("The main Looper has already been prepared.");}sMainLooper = myLooper();}}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));}/*** 创建一个MessageQueue消息队列* @param quitAllowed*/private Looper(boolean quitAllowed) {mQueue = new MessageQueue(quitAllowed);mThread = Thread.currentThread();}private static boolean loopOnce(final Looper me,final long ident, final int thresholdOverride) {// 通过消息队列中next指针获取消息 如果没有消息会调native方法去阻塞Message msg = me.mQueue.next(); // might blockif (msg == null) {// No message indicates that the message queue is quitting.return false;}/*** 可以考虑做卡顿问题的分析* 可以Looper.getMainLooper().setMessageLogging(printer)打印出这个日志* * logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);* 存在字符串拼接,频繁调用会创建大量对象造成内存抖动* 后台线程频繁获取主线程堆栈对性能有一定影响,获取主线程堆栈会暂停主线程的运行*/// This must be in a local variable, in case a UI event sets the loggerfinal Printer logging = me.mLogging;if (logging != null) {logging.println(">>>>> Dispatching to " + msg.target + " "+ msg.callback + ": " + msg.what);}// Make sure the observer won't change while processing a transaction.final Observer observer = sObserver;final long traceTag = me.mTraceTag;long slowDispatchThresholdMs = me.mSlowDispatchThresholdMs;long slowDeliveryThresholdMs = me.mSlowDeliveryThresholdMs;if (thresholdOverride > 0) {slowDispatchThresholdMs = thresholdOverride;slowDeliveryThresholdMs = thresholdOverride;}final boolean logSlowDelivery = (slowDeliveryThresholdMs > 0) && (msg.when > 0);final boolean logSlowDispatch = (slowDispatchThresholdMs > 0);final boolean needStartTime = logSlowDelivery || logSlowDispatch;final boolean needEndTime = logSlowDispatch;if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {Trace.traceBegin(traceTag, msg.target.getTraceName(msg));}final long dispatchStart = needStartTime ? SystemClock.uptimeMillis() : 0;final long dispatchEnd;Object token = null;if (observer != null) {token = observer.messageDispatchStarting();}long origWorkSource = ThreadLocalWorkSource.setUid(msg.workSourceUid);try {// 获取消息中的Handler进行消息的分发msg.target.dispatchMessage(msg);if (observer != null) {observer.messageDispatched(token, msg);}dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;} catch (Exception exception) {if (observer != null) {observer.dispatchingThrewException(token, msg, exception);}throw exception;} finally {ThreadLocalWorkSource.restore(origWorkSource);if (traceTag != 0) {Trace.traceEnd(traceTag);}}if (logSlowDelivery) {if (me.mSlowDeliveryDetected) {if ((dispatchStart - msg.when) <= 10) {Slog.w(TAG, "Drained");me.mSlowDeliveryDetected = false;}} else {if (showSlowLog(slowDeliveryThresholdMs, msg.when, dispatchStart, "delivery",msg)) {// Once we write a slow delivery log, suppress until the queue drains.me.mSlowDeliveryDetected = true;}}}if (logSlowDispatch) {showSlowLog(slowDispatchThresholdMs, dispatchStart, dispatchEnd, "dispatch", 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();return true;}
MessageQueueMessageQueue(boolean quitAllowed) {mQuitAllowed = quitAllowed;/*** 初始化Native方法,返回值NativeMessageQueue指针地址*/mPtr = nativeInit();}Message next() {// Return here if the message loop has already quit and been disposed.// This can happen if the application tries to restart a looper after quit// which is not supported.final long ptr = mPtr;if (ptr == 0) {return null;}int pendingIdleHandlerCount = -1; // -1 only during first iterationint nextPollTimeoutMillis = 0;for (;;) {if (nextPollTimeoutMillis != 0) {Binder.flushPendingCommands();}/***** 阻塞操作,nextPollTimeoutMillisddd等待时长* nativePollOnce用于“等待”, 直到有下一条消息可用为止* nextPollTimeoutMillis 为-1则阻塞*/nativePollOnce(ptr, nextPollTimeoutMillis);synchronized (this) {// Try to retrieve the next message.  Return if found.final long now = SystemClock.uptimeMillis();Message prevMsg = null;Message msg = mMessages;// 判断是不是异步消息if (msg != null && msg.target == null) {// Stalled by a barrier.  Find the next asynchronous message in the queue.do {prevMsg = msg;msg = msg.next;} while (msg != null && !msg.isAsynchronous());}if (msg != null) {// 从消息队列中拿到的Message的执行时间,比当前时间还后面,则计算其差值,用于后面休眠。if (now < msg.when) {// Next message is not ready.  Set a timeout to wake up when it is ready.nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);} else {// 如果从消息队列中获取的Message小于当前时间,则返回给Looper进行派发和处理// Got a message.mBlocked = false;if (prevMsg != null) {prevMsg.next = msg.next;} else {mMessages = msg.next;}msg.next = null;if (DEBUG) Log.v(TAG, "Returning message: " + msg);msg.markInUse();return msg;}} else {// No more messages.// 消息队列中没有更多的消息了。则进行长时间休眠 -1代表长时间等待nextPollTimeoutMillis = -1;}// Process the quit message now that all pending messages have been handled.if (mQuitting) {dispose();return null;}// If first time idle, then get the number of idlers to run.// Idle handles only run if the queue is empty or if the first message// in the queue (possibly a barrier) is due to be handled in the future.if (pendingIdleHandlerCount < 0&& (mMessages == null || now < mMessages.when)) {pendingIdleHandlerCount = mIdleHandlers.size();}if (pendingIdleHandlerCount <= 0) {// No idle handlers to run.  Loop and wait some more.mBlocked = true;continue;}if (mPendingIdleHandlers == null) {mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];}mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);}/*** 如果没有消息处理* 判断是否存在闲时处理器调用queueIdle方法*/// Run the idle handlers.// We only ever reach this code block during the first iteration.for (int i = 0; i < pendingIdleHandlerCount; i++) {final IdleHandler idler = mPendingIdleHandlers[i];mPendingIdleHandlers[i] = null; // release the reference to the handlerboolean keep = false;try {// 如果返回false则只处理一次 并且移除这个闲时处理器keep = idler.queueIdle();} catch (Throwable t) {Log.wtf(TAG, "IdleHandler threw exception", t);}if (!keep) {synchronized (this) {mIdleHandlers.remove(idler);}}}// Reset the idle handler count to 0 so we do not run them again.pendingIdleHandlerCount = 0;// While calling an idle handler, a new message could have been delivered// so go back and look again for a pending message without waiting.nextPollTimeoutMillis = 0;}}boolean enqueueMessage(Message msg, long when) {if (msg.target == null) {throw new IllegalArgumentException("Message must have a target.");}synchronized (this) {if (msg.isInUse()) {throw new IllegalStateException(msg + " This message is already in use.");}if (mQuitting) {IllegalStateException e = new IllegalStateException(msg.target + " sending message to a Handler on a dead thread");Log.w(TAG, e.getMessage(), e);msg.recycle();return false;}msg.markInUse();msg.when = when;Message p = mMessages;boolean needWake;if (p == null || when == 0 || when < p.when) {// 如果p为空,表明消息队列中没有消息,那么msg将是第一个消息,needwake需要根据mBlocked复值// New head, wake up the event queue if blocked.msg.next = p;mMessages = msg;needWake = mBlocked;} else {// 如果p不为空,表明消息队列中还有剩余的消息,需要将新的msg添加到对应的位置。// Inserted within the middle of the queue.  Usually we don't have to wake// up the event queue unless there is a barrier at the head of the queue// and the message is the earliest asynchronous message in the queue.needWake = mBlocked && p.target == null && msg.isAsynchronous();Message prev;for (;;) {prev = p;p = p.next;// 从消息队列中取出消息,判断该消息的触发时间,与要新添加的Message的时间对比。// 如果新添加的Message时间小于 当前消息队列中获取的Message的时间,则直接break。if (p == null || when < p.when) {break;}if (needWake && p.isAsynchronous()) {needWake = false;}}// 将新添加的Message添加到该队列的指定位置msg.next = p; // invariant: p == prev.nextprev.next = msg;}// 判断是否需要唤醒// We can assume mPtr != 0 because mQuitting is false.if (needWake) {// 调用nativeWake,触发nativePollOnce函数结束等待。nativeWake(mPtr);}}return true;}
Handlerpublic Handler() {this(null, false);}/*** 外部传递一个looper* @param looper*/public Handler(@NonNull Looper looper) {this(looper, null, false);}public Handler(@Nullable Callback callback) {this(callback, false);}public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async) {mLooper = looper;      // Handler中会持有消息循环器mQueue = looper.mQueue;// Handler中会持有消息队列mCallback = callback;mAsynchronous = async;}public final boolean post(@NonNull Runnable r) {return  sendMessageDelayed(getPostMessage(r), 0);}public final boolean postAtTime(@NonNull Runnable r, long uptimeMillis) {return sendMessageAtTime(getPostMessage(r), uptimeMillis);}public final boolean postAtTime(@NonNull Runnable r, @Nullable Object token, long uptimeMillis) {return sendMessageAtTime(getPostMessage(r, token), uptimeMillis);}public final boolean postDelayed(@NonNull Runnable r, long delayMillis) {return sendMessageDelayed(getPostMessage(r), delayMillis);}public final boolean postDelayed(Runnable r, int what, long delayMillis) {return sendMessageDelayed(getPostMessage(r).setWhat(what), delayMillis);}private static Message getPostMessage(Runnable r) {Message m = Message.obtain();m.callback = r;return m;}public final boolean sendMessage(@NonNull Message msg) {return sendMessageDelayed(msg, 0);}public final boolean sendEmptyMessage(int what){return sendEmptyMessageDelayed(what, 0);}public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {Message msg = Message.obtain();msg.what = what;return sendMessageDelayed(msg, delayMillis);}public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {if (delayMillis < 0) {delayMillis = 0;}return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);}public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {MessageQueue queue = mQueue; // 如果消息队列为null直接退出if (queue == null) {RuntimeException e = new RuntimeException(this + " sendMessageAtTime() called with no mQueue");Log.w("Looper", e.getMessage(), e);return false;}return enqueueMessage(queue, msg, uptimeMillis);}private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,long uptimeMillis) {msg.target = this;// 把当前Handler对象复值msg.workSourceUid = ThreadLocalWorkSource.getUid();if (mAsynchronous) {msg.setAsynchronous(true);}return queue.enqueueMessage(msg, uptimeMillis);}
Handler
Handler(Looper looper):有传递消息循环器,那就直接使用该looper
Handler(Callback callback, boolean async):没有如looper就去Looper.myLooper()获取一个
Looper mLooper=Looper.myLooper()
MessageQueue mQueue= mLooper.mQueuepost(Runnable r):会自动生成一个msg然后发送出去
postAtTime(Runnable r, long uptimeMillis):会自动生成一个msg然后延迟x发送出去
sendMessageDelayed(getPostMessage(r), 0):得到msg发送消息sendMessage(Message msg):发送一个指定msg
sendMessageDelayed(Message msg, long delayMillis)延迟发送一个指定msg
sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis):方法中会得到mQueue 即消息队列MessageQueue
enqueueMessage(queue, msg, uptimeMillis):该方法msg.target=this;意味着msg中持有一个handler;通过queue.enqueueMessage(msg, uptimeMillis)把msg消息以链表的结构存储(先进先出原则)Looper
Looper(boolean quitAllowed)唯一的构造方法,quitAllowed是否支持停止消息循环
mQueue = new MessageQueue(quitAllowed);构造方法中构造消息队列对象
mThread = Thread.currentThread();loop():开启消息循环唯一入口
Looper me = myLooper()判断当前Looper是否存在不存在抛出异常
for()开启循环
Message msg = me.mQueue.next():获取消息队列中的消息
msg.target.dispatchMessage(msg)把消息分发下去
msg.callback != null->handleCallback(msg):callback实现Runnable其run()做处理工作;
mCallback != null->mCallback.handleMessage(msg): mCallback实现Callback由其handleMessage进行处理;
handleMessage(msg):通过重写Handler中handleMessage(msg)处理消息.MessageQueue
Message next():开启消息读取
nativePollOnce(ptr, nextPollTimeoutMillis):表示下一次轮询超时时间,nextPollTimeoutMillis=-1没有消息需阻塞,0开启新一轮或已经执行完idle闲时事件处理
keep = idler.queueIdle():如没消息执行该方法,返回false移除这个接口,否则不移除boolean enqueueMessage(Message msg, long when)
msg.target == null 如果Handler为null直接抛出异常
needWake为true说明有消息加入需要处理nativeWake(mPtr)通知其next()中需要处理数据注意:可以使用闲暇handler做一些不是很急需的事情
Looper.myQueue().addIdleHandler(IdleHandler接口 handler)
IdleHandler接口实现queueIdle()返回值:false该queueIdle只执行一次,true该queueIdle可在空闲时直执行针对app主线程崩溃问题
我们可以对dispatchMessage方法进行异常捕获,但是该方法是由Looper.loop中的消息触发,所以无法捕获该异常。
但是我们可以对Looper的loop方法进行一个异常捕获,保证所有主线程的异常全部被捕获到。
为什么可以这么说?
因为Looper.loop是开启所有主线程消息循环,在ActivityThread.main中被开启执行。
故我们可以发送一个消息去执行自己开启的loop方法
比如:Log.e(TAG, "通过handler发送数据执行run 如果不通过发送消息方式可能会阻塞后面运行的程序");new Handler(Looper.getMainLooper()).post(() -> {Log.e(TAG, "死循环为保证每次捕获崩溃之后能再次开启消息循环");while (true) {try {Log.e(TAG, "保证崩溃之后被try住异常 同时记录主线程崩溃次数和崩溃信息");Looper.loop();} catch (Throwable e) {mainCount++;Log.e(TAG, "当前主线程崩溃次数==" + mainCount + "==崩溃信息:" + e.getMessage());}}});

Android-33源码分析: Handler消息机制相关推荐

  1. android smack源码分析——接收消息以及如何解析消息

    2019独角兽企业重金招聘Python工程师标准>>> 在android里面用的smack包其实叫做asmack,该包提供了两种不同的连接方式:socket和httpclient.该 ...

  2. miniGUI源码分析:消息机制

    miniGUI通过接收消息来和外界交互.消息由系统或应用程序产生,系统对输入事件产生消息,系统对应用程序的响应也会产生消息,应用程序可以通过产生消息来完成某个任务,或者与其它应用程序的窗口进行通讯.总 ...

  3. Android HandlerThread 源码分析

    HandlerThread 简介: 我们知道Thread线程是一次性消费品,当Thread线程执行完一个耗时的任务之后,线程就会被自动销毁了.如果此时我们又有一 个耗时任务需要执行,我们不得不重新创建 ...

  4. Android ADB 源码分析(三)

    前言 之前分析的两篇文章 Android Adb 源码分析(一) 嵌入式Linux:Android root破解原理(二) 写完之后,都没有写到相关的实现代码,这篇文章写下ADB的通信流程的一些细节 ...

  5. Memcached源码分析 - 内存存储机制Slabs(5)

    Memcached源码分析 - 网络模型(1) Memcached源码分析 - 命令解析(2) Memcached源码分析 - 数据存储(3) Memcached源码分析 - 增删改查操作(4) Me ...

  6. 9. 源码分析之消息消费

    源码分析之消息消费 Rebalance(针对集群消费模式) (1)消费Group下的所有消费者 (2)Topic的所有Queue队列 (3)Queue分配策略 触发时机 (1)消费者启动 (2)消费者 ...

  7. 【Android SDM660源码分析】- 02 - UEFI XBL QcomChargerApp充电流程代码分析

    [Android SDM660源码分析]- 02 - UEFI XBL QcomChargerApp充电流程代码分析 一.加载 UEFI 默认应用程序 1.1 LaunchDefaultBDSApps ...

  8. 【Android SDM660源码分析】- 03 - UEFI XBL GraphicsOutput BMP图片显示流程

    [Android SDM660源码分析]- 03 - UEFI XBL GraphicsOutput BMP图片显示流程 1. GraphicsOutput.h 2. 显示驱动初化 DisplayDx ...

  9. 【Android SDM660源码分析】- 01 - 如何创建 UEFI XBL Protocol DXE_DRIVER 驱动及UEFI_APPLICATION 应用程序

    [Android SDM660源码分析]- 01 - 如何创建 UEFI XBL Protocol DXE_DRIVER 驱动及UEFI_APPLICATION 应用程序 一.创建DXE_DRIVER ...

最新文章

  1. codeforces 739E - Gosha is hunting
  2. 后端开发:数据持久化框架为什么放弃Hibernate、JPA、Mybatis,最终选择JDBCTemplate!...
  3. Drools集成SpringBoot
  4. 矢量算法java,矢量线的一种栅格化算法
  5. 【Mac】Mac通过反向代理连接内网(教育网)服务器 + 免密登陆
  6. 两节锂电池保护IC,芯片电路图如何设计
  7. 第四周作业-多线程编程
  8. 图的深度遍历(邓俊辉版)
  9. Maximo 人员- 应用程序导入,公共操作怎么配置,求大神指点,万分感谢
  10. m451dn linux驱动下载,惠普M451dn驱动下载
  11. vue3+vite+antd——后台管理系统——基础模板
  12. 从两年一次到一年三次,百度频繁调整架构为哪般?
  13. 单片机程序跑飞的原因
  14. 83. 测试是软件开发的工程严谨度
  15. C/C++中的atan和atan2函数
  16. pythoc_autocad_标注_all_横线_竖线
  17. 程序员,在什么情况下加班是可接受的
  18. Python爬取猫眼「碟中谍」全部评论
  19. Statistical Phrase-Based Translation_2003_Koehn【SMT】
  20. HTB OnlyForYou WriteUp

热门文章

  1. ByteBuffer中的flip()、clear()、compact()
  2. 米家智能家居经常离线_所有智能家居集线器已经足够
  3. Altium designer如何将制作一个自己的logo
  4. 【狂神说】Docker网络基础笔记整理+重点详解
  5. echarts饼图指示器文字颜色设置不同
  6. ubuntu 中文输入法安装
  7. python restful接口自动化_从未见过如些清新脱俗的完整Python+requests接口自动化测试框架搭建文章!...
  8. C#WinForm开发笔记——基本控件(二)
  9. 机器学习经典算法之KNN
  10. 贺岁片《大腕》经典台词片段