a.
1.handler源码架构解析
2.一个线程有几个looper?如何保证
3.Handler内存泄露的原因?其它内部类为什么没有这个问题?
4为什么主线程可以new Handler?其它子线程可以吗?怎么做?
5.子线程中维护的Looper在消息队列无消息的时候处理方案是怎样的?
6.Looper死循环为什么不会导致应用卡死?
7.使用Handler的PostDelay后消息队列会有什么变化?
b.
handler
looper
message
messageQueue:优先级队列(链表):按时间排序的队列
Thread 去调用Looper.loop (死循环for(;;))作为动力
c.
sendMessage()...||postMessage()....
--->sendMessageAtTime()
--->MessageQueue.enqueueMessage()
Looper.loop
--->msg=MessageQueue.next() --->if(msg==null)退出死循环(动力停止)
--->msg.target.dispatchMessage(msg)
--->Handler.handleMessage(msg)
1. 一个线程有几个Handler
多个
2.一个线程有几个Looper,如何保证(涉及线程安全,并发编程)
threadLocal(线程隔离)为final唯一
<key,value>Map
每个Thread都对应一个ThreadLocalMap,这个map.set<key,value>,key是当前这个ThreadLocal,value是一个Looper。用这种方式将ThreadLocal和Looper唯一绑定
3. Handler 内存泄露的原因:持有activity
匿名内部类
内部类特征:持有外部类的对象
Handler 内存泄露,为什么其他内部类没有类似问题。
Handler的处理流程
enqueueMessage()方法里将message.target=this(Handler)。target将在消息发送前(尤其是delay)一直持有这个Handler,而这个Handler一直持有外部类对象,所以造成内存泄漏。
解决办法:静态内部类不会持有外部对象。或者弱引用
4.为什么在主线程可以new Handler,如果需要在子线程new Handler,需要做什么。
launcher--->zygote--->application(Dalvik/Art虚拟机)--->ActivityThread.Main函数--->Looper.prepareMainLooper()&Loop.loop()
需要在子线程new Handler,需要做:Looper.prepare()&Loop.loop();
5.子线程维护的Looper,消息队列无消息的时候的处理方式是什么,有什么用?
nativePollOnce--->linux--->epoll--->messageQueue
handler的睡眠和唤醒机制
主线程需要释放吗?(Looper.quit())为什么?
AMS(activityManagerSeivice) 通过Handler去管理;
四大组件的底层Binder
retrofit:@multipart @body(注解+动态代理+反射+okhttp)
6.既然可以存在多个handler往messageQueue中添加消息,发送消息时,各个handler可能处于不同线程中,那他内部如何确保线程安全。
一个线程-->一个Looper-->一个MessageQueue(final)
synchronized(this) :内置锁this代表messageQueque (并发编程)
7. 使用Message时,怎么创建?
享元设计模式:obtain 每次获取从队列中获取,每次用完后不直接将message==null,而是把message的成员变量置空,然后将message对象放入队列中,重复使用。
JVM:
new 分配一块内存 然后 destory 造成内存抖动 甚至OOM;
8. Looper死循环为什么不会导致应用卡死。
综合性问题:AMS和Handler源码,多线程
ANR:应用卡死的原因
a. 5s之内没有响应输入的事件,比如按键,屏幕触摸。(UI消息没有及时处理)
b. 广播接受器在10s内没有执行完。
AMS管理机制:
每一个应用都存在于自己的虚拟机中,也就是说每一个应用都有自己的一个Main函数。
启动流程:launcher--->zygote--->application(Dalvik/Art虚拟机)--->ActivityThread--->Main函数
所有应用所有生命周期的函数(包括Activity,service的所有生命周期)都运行在这个Looper里面,他们都是以消息的形式存在。
为什么主线程Looper休眠很长时间也不会出现ANR?(Looper中没有消息时会阻塞)
anr的主要原因是,message队列里面有消息(ui响应时间)需要处理,但没及时处理,比如前一条消息耗时超过5s,造成队列阻塞,后面消息也处理不了,卡死了。与Looper的睡眠没有任何关系。