0%

Android_Handler部分整理

Handler 整理

Handler相关
1.谈谈消息机制Handler作用?有哪些要素?流程是怎样的?
考点:

作用
四大要素
具体流程
参考答案:

Handler的作用主要是与UI线程进行通信和延迟任务执行
四大要素:Message、MessageQueue、Handler、Looper
MessageQueue负责消息的存储与管理,使用单链表实现,为了快速插入和删除,在其next()方法无限循环判断是否有新消息,有就返回并移除
Handler负责Message的发送和处理
Looper负责关联线程和分发消息,在该线程的MessageQueue中取Message,分发给Handler。
Looper在创建的时候会创建一个MessageQueue,调用loop()方法开始消息循环,然后不断调用MessageQueue的next()方法,有消息处理,没有就阻塞。
2.一个线程能否创建多个Handler,Handler跟Looper之间的对应关系?
对于一个线程来说,只能有一个Looper,创建Looper的时候创建一个MessageQueue,可以分发到多个Handler
—> 可以从Looper扩展到ThreadLocal

3.Handler的内存泄露原因和解决方案
根本原因:Handler允许延时消息和Message持有Handler,Handler作为内部类会持有外部类,如果延时期间Activity被关闭,该Activity会被泄露。
解决方法:Handler定义为静态内部类,内部持有Activity的弱引用,并且在onDestroy中移除所有消息

4.UI设计为何都是单线程的?
UI采用单线程模型的原因是,加锁会让UI的访问逻辑变得复杂且低效

5.Looper死循环为什么不会导致应用卡死?

主线程的主要方法就是消息循环,一旦退出消息循环,表示应用退出了
造成ANR的原因不是主线程阻塞,而是主线程的Looper消息处理没有在预期内完成
阻塞和ANR没有必然联系,ANR只是消息处理机制中的一个预警机制
无消息时,native调用的是epoll_wait,本身阻塞,不消耗CPU时间片
6.Handler的延时是怎么实现的?精确吗?
考点:

底层实现延迟的原理
不精确的原因?
如何优化?
参考答案:

Handler如何实现延迟?
MessageQueue(单链表实现)的enqueue为入口调用到Message的next方法获取消息
进入一个for(;;)的大死循环,不断调用nativePollOnce,其中nextPollTimeoutMills为-1表示阻塞且不会超时,为0表示立即返回,大于0表示下一次唤醒的时间
唤醒时间是从开机开始计算的
不精确的原因是如果任务堆积太多或者任务很耗时,会导致Looper负载很高,进而导致卡顿
解决方法:从消息队列优化和Looper入手
队列优化(重复消息过滤、互斥消息取消、复用消息)
Looper:利用IdleHandler(空闲)和HandlerThread(避免主线程太挤)
7.可以在子线程中直接new一个Handler吗?
考点:

子线程能否使用Handler?
子线程怎么使用Handler?
多次prepare有什么问题?
参考答案:

直接new肯定是不可以的,主线程可以直接使用Handler是因为Activity内部包含一个Looper对象,而对于子线程来说,干干净净,没有帮我们创建Looper对象,所以需要自己手动维护,创建Looper,并开启Looper循环。
多次prepare会抛运行时异常<为了保证一个线程对应一个Looper>
小细节点:Message的创建可以用obtain,利用消息池化,避免生成过多的Message实例<有的说默认大小是10,看28的代码是50,不过这不重要>

Link:
1: https://www.jianshu.com/p/f34e5e21fa0d