1、Android异步消息传递机制有以下两个方式:(异步消息传递来解决线程通信问题)

handler 和 AsyncTask

2、handler官方解释的用途:

1)、定时任务:通过handler.postDelay(Runnable r, time)来在指定时间执行msg.

2)、线程间通信:在执行较为耗时操作的时候,在子线程中执行耗时任务,然后handler(主线程的)把执行的结果通过sendmessage的方式发送给UI线程去执行用于更新UI.

3、handler源码分析

一、在ActivityThread.main(应用程序的入口函数,主线程中执行)

看到第5401行代码功能是生成了一个主线程的Looper对象。

100->90行生成Lopper并扔到ThreadLocal中。

105标记生成的Lopper为主线程的Looper。

5417功能是,新生成的Lpooer不断去loop消息队列,消息队列后面介绍。

一个线程只能有一个Lopper, 主线程默认在启动时候已经由系统创建完成,这也就代表,我们自己写的线程要使用消息传递机制,需要自己生成looper并调用looper.loop去循环消息队列。

看下looper.loop循环的是什么?

127看到一个looper有一个MessageQueue,134开始是不断的从messageQueue中取出message交给148msg.target.dispatchMessage去处理。

二、看下消息传递的源码

handler属于它建立的线程。也就是说handler如果在主线程中创建,那么他处理消息就是在主线程中处理,如果实在子线程中建立,那么消息的处理就在子线程中进行。

1、我们都知道通过handler发送消息有以下几种方式:

handler.sendMessage(msg);

hadler.sendMessageDelayed(msg, time);

sendEmptyMessage(int what);

public final boolean sendEmptyMessageDelayed(int what, long delayMillis)

其中,sendEmptyMessage的实现

只是把传进去的what写在了message里

几个函数最后都变成调用public boolean sendMessageAtTime(Message msg, long uptimeMillis)

600行把msg放到了Looper的messageQueue中。

接下来看enqueueuMessage中做了什么:

551开始,根据msg中携带的时间信息,找到当前时间要执行的msg,放在messageQueue队首。

那消息在消息队列中是怎么样被执行的呢,这就要看下loop函数

主要看下148行,是把msg交给msg.target的dispatchMessage函数来执行的,那msg.target又是哪个对象呢?

handler的enqueueMessage中看到msg.target就是handler.

所以可以看到msg最终是在handler的dispatchMessage中执行的。

看到这个函数中首先哦按段msg.callback为空的话就会调用handler的handleMessage.

至此handler处理消息的整个源码过程分析完毕。

三、除了发送消息之外,还有一下几种方式可以在子线程中发送UI跟新操作。

Handler.post

View.post

Activity.runonUithread

1、Handler.post

还是调用的sendMessageDelayed,看下getPostMeassage源码

看到msg的callback被设置成了Runnable。再回头看下上面dispatchMessage的源码,这时候msg.callback不会空,回去执行handlecallback

直接执行Runnable中的run方法。

总结一下,也就是说使用handler的post方法相当于是把带callback的msg入队列了,然后在去除msg时候,直接调用的callback的run方法。

注意点:google建议我们在写message的时候,最好使用Message.obtain()或者Handler.obtainMessage()来获取当前looper的message,而不是自己去new Message,这样做的好处是Message.obtain()会从消息池中获取一个Message对象,如果消息池中是空的,才会使用构造方法实例化一个新Message,这样有利于消息资源的利用,msg也可以更好的被回收池回收。

2、View.post

就是调用的handler的post方法,所以同上一个流程。

3、Activity.runonUithread

看实现功能是,查看当前线程是否是主线程,如果是直接执行run方法,不是的话,调用handler的post方法,注释解析的也是再清晰不过了。

补充:看下message的几个成员变量

在我们传递message的时候可以设置如上变量值(如下4条参考http://blog.csdn.net/ahuier/article/details/17012005

1) arg1 和 arg2 都是Message自带的用来传递一些轻量级存储int类型的数据,比如进度条的数据等。通过这个数据是通过Bundle的方式来转载的,读者可以自己查阅源代码研究。

2) obj 是Message自带的Object类型对象,用来传递一些对象。兼容性最高避免对齐进行类型转换等。

3) replyTo 是作为线程通信的时候使用.

4) what 用户自定义的消息码让接受者识别消息种类,int类型。

关于Message中message是怎么分配以及回收的?

Message中有很多重载函数obtain(),通过这个函数可以在Message的message Pool中获得message(Message Pool中有10个Message,sPool指向待分配的message ),message的分配就是取出aPool指向的message, 每个message的回收是通过handler的removecallbacks到MessageQueue中的removeMessag再到Message中的recycle来回收的,回收后,message被放在Message pool中。

四、HandlerThread

handlerThread继承自Thread类,并且内部封装了一个looper,在他的run方法里,实例化了looper,并且调用了looper.prepare。所以使用HandlerThread可以创建一套在子线程中传递消息的handler通信。

查看IntentService源码,可以看到在onCreate中通过HandlerThread创建了一套子线程通信相关的handler和自定义的ServiceHandler,然后再onStart函数中,通过ServiecHandler.sendMessage,ServiecHandler的handleMessage中调用了onHandleIntent方法,从而实现了IntentService中的onHandleIntent是在子线程中执行的。

Handler handler = new Handler(); 这个handler实例化依附的looper是获得当前程序所在线程的looper,所以在Activity中直接通过这种方式实例化的handler是主线程的handler。

五、ThreadLocal

ThreadLocal可以在不同的线程之中互不干扰地存储并提供数据!

ThreadLocal是与线程相关的一个类,ThreadLocal中存储的是各个线程相关的变量,所有线程共享一个ThreadLocal。Android中ThreadLocal的泛型类就是Looper。

所以新建一个线程,Looper是一个与线程相对应的类,而Looper的存储是依赖于ThreadLocal的,所以一个线程中如果用到消息传递机制,就必须要调用Looper.prepare来新建一个Looper对象(prepare函数内部实现,就是新建一个当前线程的Looper并且把它放作为这个线程的value放到ThreadLocal中)。

Android异步消息传递机制源码分析的更多相关文章

  1. Android事件分发机制源码分析

    Android事件分发机制源码分析 Android事件分发机制源码分析 Part1事件来源以及传递顺序 Activity分发事件源码 PhoneWindow分发事件源码 小结 Part2ViewGro ...

  2. ApplicationEvent事件机制源码分析

    <spring扩展点之三:Spring 的监听事件 ApplicationListener 和 ApplicationEvent 用法,在spring启动后做些事情> <服务网关zu ...

  3. Springboot学习04-默认错误页面加载机制源码分析

    Springboot学习04-默认错误页面加载机制源码分析 前沿 希望通过本文的学习,对错误页面的加载机制有这更神的理解 正文 1-Springboot错误页面展示 2-Springboot默认错误处 ...

  4. Android线程间异步通信机制源码分析

    本文首先从整体架构分析了Android整个线程间消息传递机制,然后从源码角度介绍了各个组件的作用和完成的任务.文中并未对基础概念进行介绍,关于threadLacal和垃圾回收等等机制请自行研究. 基础 ...

  5. Android查缺补漏(View篇)--事件分发机制源码分析

    在上一篇博文中分析了事件分发的流程及规则,本篇会从源码的角度更进一步理解事件分发机制的原理,如果对事件分发规则还不太清楚的童鞋,建议先看一下上一篇博文 <Android查缺补漏(View篇)-- ...

  6. android高级---->AsyncTask的源码分析

    在Android中实现异步任务机制有两种方式,Handler和AsyncTask,它在子线程更新UI的例子可以参见我的博客(android基础---->子线程更新UI).今天我们通过一个小的案例 ...

  7. Android面试题-OkHttp3源码分析

    本文配套视频: okhttp内核分析配套视频一 okhttp内核分析配套视频二 okhttp内核分析配套视频三 源码分析相关面试题 Volley源码分析 注解框架实现原理 基本使用 从使用方法出发,首 ...

  8. Android Handler消息机制源码解析

    好记性不如烂笔头,今天来分析一下Handler的源码实现 Handler机制是Android系统的基础,是多线程之间切换的基础.下面我们分析一下Handler的源码实现. Handler消息机制有4个 ...

  9. 【Cocos2d-x 3.x】 事件处理机制源码分析

    在游戏中,触摸是最基本的,必不可少的.Cocos2d-x 3.x中定义了一系列事件,同时也定义了负责监听这些事件的监听器,另外,cocos定义了事件分发类,用来将事件派发出去以便可以实现相应的事件. ...

随机推荐

  1. python(10): xlsxwriter模块

    import xlsxwriter as writer 注意: xlsxwriter 只能创建新文件,不可以修改原有文件.如果创建新文件时与原有文件同名,则会覆盖原有文件. import xlsxwr ...

  2. 拓展中国剩余定理(ex_crt)

    一般来讲,crt(中国剩余定理)比较常见,而ex_crt(拓展中国剩余定理)不是很常用 但是noi 2018偏偏考了这么个诡异的东西... 所以这里写一个ex_crt模板 模型: 求一个x满足上述方程 ...

  3. Eclipse中java文件生成jar文件的方法

    在eclpse中找到你要导出的java程序 选中它   单击文件 -->export   在弹出的export对话框中找到 jar File 单击选中-->next   按图示顺序依次 选 ...

  4. 饮冰三年-人工智能-linux-09 服务

    1:SSH服务(提供远程连接服务) 客户端使用Xshell 链接成功 加快连接速度 关闭防火墙 2:apache 服务(提供网页服务) 2.0 准备环境 关闭防火墙:service iptables ...

  5. Just oj 2018 C语言程序设计竞赛(高级组)F:Star(结构体排序+最小生成树)

    F: Star Time Limit: 1 s      Memory Limit: 128 MB Submit My Status Problem Description 31世纪,人类世界的科技已 ...

  6. POJ 2001 Shortest Prefixes(字典树活用)

    Shortest Prefixes Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 21651   Accepted: 927 ...

  7. 史上最简单的SpringCloud教程 | 第九篇: 服务链路追踪(Spring Cloud Sleuth)

    这篇文章主要讲述服务追踪组件zipkin,Spring Cloud Sleuth集成了zipkin组件. 注意情况: 该案例使用的spring-boot版本1.5.x,没使用2.0.x, 另外本文图3 ...

  8. windows环境下永久修改pip镜像源的方法(转)

    一.在windows环境下修改pip镜像源的方法(以python3.7为例) (1):在windows文件管理器中,输入 %APPDATA%,cmd里面输入即可. (2):会定位到一个新的目录下,在该 ...

  9. java编译通过,为什么运行却提示找不到或无法加载主类?

    java编译通过,为什么运行却提示找不到或无法加载主类? https://www.zhihu.com/question/36537093 这边提供一个关于程序中含有package关键字,使用“终端”运 ...

  10. java线程间的通信方式

    1.同步 synchronized 2.轮询 while   volatile 3.wait/notify机制 syncrhoized加锁的线程的Object类的wait()/notify()/not ...