1.handler线程切换原理
消息发送和消费两者之间是基于内存共享机制,共享一份消息队列。采用ThreadLocal对线程进行管理,保证 每个线程上的Looper是相互独立的。在发送消息的过程中由Message去持有发送者的实例(Handler),导致处理消息的时候是哪个线程上创建的Handler就在那个线程上处理消息。
2.Looper为什么不会阻塞主线程?
ActivityThread main方法是Android app的入口,Looper.loop()方法必须死循环挂起,它如果挂掉了,整个进程就挂掉了。
3.Handler为什么会存在内存泄漏问题?
a.内部类默认会持有外部类的引用,所以如果在Activity中通过匿名内部类的方式创建Handler的话,Handler会持有activity的引用。
b.如果Handler在主线程中创建的话,在Looper 的prepareMainLooper方法中将该loop赋值给sMainLooper,而sMainLooper是静态变量,进程启动,类被加载,静态变量就被分配内存,当进程结束,静态变量才会销毁。
就会有以下持有链:
sMainLooper(sMainLooper要在进程结束的时候才会被销毁)->Looper->MessageQueue->Message->Handler->Activity
所以如果发送延迟消息或是将Handler作为定时器使用的时候就会出现内存泄漏问题(message还在等待被消费,但是退出了当前activity,那么这里持有的activity的实例无法回收)
解决办法:
创建Handler的时候避免使用匿名内部类的方式,如果需要向handler中传入其他对象实例的时候,使用弱引用的方式
4.如何创建Message?
使用Message.obtain()获取 消息实例,采用了享元设计模式,从回收池中获取的。
5.Handler如何处理延迟消息的?
Message进入的时候使用当前时间加上延迟时间作为优先级,根据优先级排列整个 Message链表,在取的时候直接取链表的第一个message,如果时间没到等待,如果时间到了开始执行,依次往下执行。
参考学习链接:
手撕 FrameWork源码,从Binder → Handler → Zygote → AMS → PMS → WMS 彻底讲穿原理_哔哩哔哩_bilibili