码迷,mamicode.com
首页 > 移动开发 > 详细

Android异步消息传递机制源码分析&&相关知识常被问的面试题

时间:2017-08-07 20:45:18      阅读:335      评论:0      收藏:0      [点我收藏+]

标签:定义   研究   需要   tde   分析   异步   事务   next   发送   

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去处理。

135:面试点

二、看下消息传递的源码

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类型。

四、常被问的相关面试题。

1、Looper.loop在message为空的时候会一直去loop吗?

解答:https://www.zhihu.com/question/34652589

连接中内容,强烈建议看下知乎完整解答,写的很好)这里就涉及到Linux pipe/epoll机制,简单说就是在主线程的MessageQueue没有消息时,便阻塞在loop的queue.next()中的nativePollOnce()方法里,此时主线程会释放CPU资源进入休眠状态,直到下个消息到达或者有事务发生,通过往pipe管道写端写入数据来唤醒主线程工作。这里采用的epoll机制,是一种IO多路复用机制,可以同时监控多个描述符,当某个描述符就绪(读或写就绪),则立刻通知相应程序进行读或写操作,本质同步I/O,即读写是阻塞的。 所以说,主线程大多数时候都是处于休眠状态,并不会消耗大量CPU资源。

2、sendMessage和post什么区别呢?

我想看完上面的分析,自然就会通了

3、msg.target是谁?

同2

 

Android异步消息传递机制源码分析&&相关知识常被问的面试题

标签:定义   研究   需要   tde   分析   异步   事务   next   发送   

原文地址:http://www.cnblogs.com/SA226343/p/7300746.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!