热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Handler+Messageu原理分析02

Handler+Messageu原理分析02-Handler流程分析在Activity当中newHandler()的时候,就已经创建了主线程的Looper对象,在Activit

Handler流程分析

在Activity当中new Handler()的时候,就已经创建了主线程的Looper对象,在ActivityThread中的main方法中进行创建。在sendMessage()的时候都会调用enqueueMessage()压入消息到消息队列里面,主要操作就是将send的message赋值给了一个全局的message(源码中变量名为MMessage)。在消息队列当中取消息的时候有个Looper.loop()方法一直在轮寻消息,按照先进先出的原则取消息,调用了queue.next方法,该方法就是将message进行返回,在next方法中就是将之前赋值的全局变量的mMessage再返回回来,之后调用handler里面的dispatchMessage()方法实现了线程切换(如果在子线程中发送了消息)而该方法调用了handlerMessage()并由实例化handler的时候重写该方法取到消息。

提到了Handler大家都会联想到另外三个对象,与Handler息息相关。如图所示

在UI线程当中使用Handler

在子线程中使用Handler

注意红框里面的代码,为什么要在子线程中写这两句话呢。我们知道项目启动会直接调用主线程中main方法去实例化looper对象并通过Looper.looper()激活消息并获取消息的一系列流程,而在子线程当中如果我们直接new Handler(),根据threadLocalMap取looper的时候肯定是为null的,报空指针,原因就是没有对Looper进行初始化,所以调用Looper.prepare()方法进行new Looper()

来看下张图 很清楚我们可以看到无论你调用post sendMessage sendEmptyMessage 等等 最终都会调用 enqueueMessage()将消息压入消息队列当中。

Handler整个流程图

Handler的post方法为什么是主线程

我们在写post方法的时候会new一个runnable,而该runerable会被封装成一个message对象进行发送消息。源码显示如下

private static Message getPostMessage(Runnable r){
   Message m = Message.obtain();
   m.callback = r;
   return m;
}

大家来看这里面message的callback被赋值了该Runnable,注意不是Handler实例化的时候new 的callback。这样就通过 sendMessageDelayed(getPostMessage(r),0)方法进行将消息发送,调用了dispatchMessage(Message msge)进行了线程的切换,该方法源码如下

 public void dispatchMessage(Message msg){
   if(msg.callback!=null){
     handleCallback(msg);
   }else{
     if(mCallbackz!=null){
       if{mCallback.handleMessage(msg);
         return;
       }
       handleMessage(msge);
     }
   }
 }
private static void handleCallback(Message message){
  message.callback.run()
}

所以最终就会在主线程中执行post方法中实现的run方法

小结

1.为什么主线程用Looper死循环不会引发ANR异常
 因为在Looper.next()开启死循环的时候,一旦需要等待时或者还没有执行到的时候,会调用NDK里面的JNI方法,
 释放当前时间片,这样就不会造成ANR异常了
2.为什么Handler构造方法里面Looper不是直接new的
如果在Handler构造方法中new Looper,怕是无法保证Looper的唯一性了,只有用Looper.prepare()才能保证唯一性,
具体看prepare方法
MessageQueue为什么要放在Looper的私有构造方法里面初始化
因为一个线程只能绑定一个Looper,所以在Looper构造方法里面初始化可以保证mQueue也是唯一的
Thread对应一个Looper对应一个mQueue
主线程里面的Looper.prepare/Looper.loop,是一直在无限循环里面的吗?
 是的

感谢

感谢大家的阅读 点个赞呗
关注我 持续更新

Github


推荐阅读
  • 重入锁(ReentrantLock)学习及实现原理
    本文介绍了重入锁(ReentrantLock)的学习及实现原理。在学习synchronized的基础上,重入锁提供了更多的灵活性和功能。文章详细介绍了重入锁的特性、使用方法和实现原理,并提供了类图和测试代码供读者参考。重入锁支持重入和公平与非公平两种实现方式,通过对比和分析,读者可以更好地理解和应用重入锁。 ... [详细]
  • 本文介绍了RxJava在Android开发中的广泛应用以及其在事件总线(Event Bus)实现中的使用方法。RxJava是一种基于观察者模式的异步java库,可以提高开发效率、降低维护成本。通过RxJava,开发者可以实现事件的异步处理和链式操作。对于已经具备RxJava基础的开发者来说,本文将详细介绍如何利用RxJava实现事件总线,并提供了使用建议。 ... [详细]
  • RabbitMq之发布确认高级部分1.为什么会需要发布确认高级部分?在生产环境中由于一些不明原因,导致rabbitmq重启,在RabbitMQ重启期间生产者消息投递失败,导致消息丢 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • 本文介绍了在MFC下利用C++和MFC的特性动态创建窗口的方法,包括继承现有的MFC类并加以改造、插入工具栏和状态栏对象的声明等。同时还提到了窗口销毁的处理方法。本文详细介绍了实现方法并给出了相关注意事项。 ... [详细]
  • linux进阶50——无锁CAS
    1.概念比较并交换(compareandswap,CAS),是原⼦操作的⼀种,可⽤于在多线程编程中实现不被打断的数据交换操作࿰ ... [详细]
  • 广度优先遍历(BFS)算法的概述、代码实现和应用
    本文介绍了广度优先遍历(BFS)算法的概述、邻接矩阵和邻接表的代码实现,并讨论了BFS在求解最短路径或最短步数问题上的应用。以LeetCode中的934.最短的桥为例,详细阐述了BFS的具体思路和代码实现。最后,推荐了一些相关的BFS算法题目供大家练习。 ... [详细]
  • 本文介绍了如何通过维持两个堆来获取一个数据流中的中位数。通过使用最大堆和最小堆,分别保存数据流中较小的一半和较大的一半数值,可以保证两个堆的大小差距为1或0。如果数据流中的数量为奇数,则中位数为较大堆的最大值;如果数量为偶数,则中位数为较大堆的最大值和较小堆的最小值的平均值。可以使用优先队列来实现堆的功能。本文还提供了相应的Java代码实现。 ... [详细]
  • 第七课主要内容:多进程多线程FIFO,LIFO,优先队列线程局部变量进程与线程的选择线程池异步IO概念及twisted案例股票数据抓取 ... [详细]
  • 工作经验谈之-让百度地图API调用数据库内容 及详解
    这段时间,所在项目中要用到的一个模块,就是让数据库中的内容在百度地图上展现出来,如经纬度。主要实现以下几点功能:1.读取数据库中的经纬度值在百度上标注出来。2.点击标注弹出对应信息。3 ... [详细]
  • java线程池的实现原理源码分析
    这篇文章主要介绍“java线程池的实现原理源码分析”,在日常操作中,相信很多人在java线程池的实现原理源码分析问题上存在疑惑,小编查阅了各式资 ... [详细]
  • RingBuffer,或者说CircularBuffer,是一个长度固定的缓冲区,当从一端插入元素超过指定的最大长度时,缓冲区另一端的元素 ... [详细]
  • 51nod3221祝寿(反向建图优化)
    题目链接感觉忘记了好多东西。求有向图中其余点到一个点的最短距离可以将该图翻转后rundijkstra#include#include ... [详细]
  • 一、死锁现象与递归锁进程也是有死锁的所谓死锁:是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作 ... [详细]
author-avatar
逗趣游戏
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有