首先looper.prepare()方法会判断是否只有一个looper 如果有多个会报错 ,然后构建出一个looper 怎么保证一个线程只持有一个looper? 每个Thread对象持有一个ThreadLocalMap对象(很像hashMap) 再看上面sThreadLocal.set方法 直接获取ThreadLocalMap对象 进行存放 key是线程 value是looper。这也解释了上面通过sThreadLocal.get()方法去进行是否looper已存在的判断。
looper.loop方法内是一个for(;;)的死循环 不过在没有消息处理的时候会进行阻塞 当有消息来时就不断取出MessageQueue中的消息 并将取出来的消息分给对应的Handler处理
ThreadLocal主要作用就是存放looper以及供Thread去取出lopper
handler造成内存泄漏的原因:
内存泄漏的本质:长生命周期对象持有了短生命周期的对象 导致短生命周期的对象不能被回收 首先app最长的生命周期的对象是 : 主线程 主线程有对应的looper以及messageQueue 这些是跟主线程绑定的不会被回收。 当子线程的handler发送一个msg时 msg.target会被赋值成handler存放在messageQueue中 这样handler就与主线程有了关联
(都是handler内的方法 this就代表handler) 然后由于handler被相关的(activity)类所持有 所以该类无法被回收
那么避免内存泄漏最简单的措施 就是给handler加static 使其变成静态 这样就与类的对象解绑了 不会影响对象的回收 当然在面对需要activity对象的成员时比如更新ui 此时需要使用弱引用
比如 private WeakReference<***Activity> weakReference; 在handler创造一个构造方法传入对应activity
public MyHandler(HandlerOOMActivity activity) {
weakReference = new WeakReference<>(activity);
this.activity = activity;
}
如果是强引用同样会产生上述情况引起内存泄漏
|