Android Handler 机制(二):Hander 机制深入探究问题梳理

时间:2020-05-10 14:32:03   收藏:0   阅读:79

一、‘非UI线程更新UI’问题探究

Android开发的时候非UI线程不能更新UI,这个是大家都知道的开发常识。但是当问到为什么?可能我们就会有些含糊了。

本文我们就针对这个问题进行探讨并进行一定的思维发散,来加深我们对Android界面刷新机制的理解。

1. UI线程的工作机制

主线程的工作机制可以概况为 生产者 - 消费者 - 队列 模型。

2. 为什么UI线程不设计成线程安全的

总所周知,如果设计成线程安全的,那性能肯定是大打折扣的,而UI更新的要求有如下特性:

所以为了保证渲染性能,UI线程不能设计成线程安全的。

3. 非UI线程一定不能更新UI吗?

答:不一定。

说明:首先Android设计了Handler机制来更新UI是避免多个子线程更新UI导致的UI错乱的问题,但是又不能通过加锁机制设计成线程安全的,因为那样会导致性能下降的很厉害。但是在Android提供的SurfaceView、GLSurfaceView里面是都能在非UI线程更新UI的。 

二、Handler发送消息的delay设置是否可靠?

答案是:不可靠。

原因:当Handler所属的线程(UI线程)要处理的内容非常多,当Looper出现事件积压的时候会使得delay不可靠。如ANR的出现就是一个最极端的代表例子。

为了理解为何在事件挤压的时候,handler会出现delay的不可靠,这里我们就加入一些核心逻辑的分析,来帮助我们进行此问题的探究。

三、Handler机制下消息队列MessageQueue的优化

一般情况下,可以考虑从以下几个方面进行优化

四、主线程的Looper为什么不会导致ANR

1. ANR的产生条件

其实最终就是最终由系统的Api发送的Message,告知相关组件发生了ANR。

这里我们使用Service举例,当Service超时的时候,发送的Message.what就是ActivityManagerService.SHOW_NOT_RESPONDING_UI_MSG。

ANR也算是Android系统提醒开发者程序编写有问题的一个机制。

2.Looper不会导致应用ANR的本质原因是什么?

当我们熟悉了Looper的工作机制,我们就会知道主线程执行的操作就是执行Loop.loop()不断的处理消息。Looper是进程上的一个概念,ANR是程序执行到某一个环节对开发者占用主线程耗时的一个监控机制,自然也就不存在Looper死循环导致ANR的问题。

3.Looper为什么不会导致CPU占用率高?(延伸)

这是因为使用了Linux底层的pipe管道机制和epoll机制,在主线程的MessageQueue没有消息时,便阻塞在loop的queue.next()中的nativePollOnce() 方法里,在没有消息时阻塞线程并进入休眠释放cpu资源,有消息时唤醒线线程,这样不会导致CPU占用率高。

 

评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!