Android-消息机制

说到Android的消息机制,其实主要说的就是Handler,它的运行需要MessageQueue和Looper。

MessageQueue用来描述消息队列。
Looper是用来创建消息队列以及进入消息循环。
Handler 是用来发送消息和处理消息。

  1. MessageQueue的内部存储了一组消息,其以队列的形式对外提供插入和删除的工作,虽然叫做消息队列,但是它的内部存储结构并不是真正的队列,而是采用单链表的数据结构来存储消息列表。
  2. Looper是为消息循环,由于MessageQueue只是消息的存储单元,它不能去处理消息,Looper会不断循环去查找是否有新消息,如果有的话就处理消息,否则就一直等待着。
    3.ThreadLocal并不是线程,它的作用是可以在每个线程中存储数据。Handler创建的时候会采用当前线程的Looper来构造消息循环系统,ThreadLocal可以在不同的线程之中互不干扰地存储并提供数据,通过ThreadLocal可以轻松获取每个线程的Looper

Android里面的Looper和iOS一样,主线程默认会初始化Looper,但是子线程需要手动去创建Looper。


Handler内存泄露

private Handler mHandler = new Handler(){
        @Override
        public void handleMessage(Message msg){
            /***/
        }
 }

我们经常会写出上面类似的代码,但是上面代码会产生内存泄露,原因是:
1.当一个Handler在主线程中被初始化。那它就一直都和Looper的消息队列相关联着。当消息被发送到Looper关联的消息队列的时候,会持有一个Handler的引用,以便于当Looper处理消息的时候,框架可以调用Handler的handleMessage(Message msg)。
2.在java中,非静态的内部类和匿名内部类都会隐式的持有一个外部类的引用。静态内部类则不会持有外部类的引用。

如何处理呢?

  1. 及时移除消息
@Override
public void onDestroy() {
   // 移除所有消息
   handler.removeCallbacksAndMessages(null);
   // 或者移除单条消息
   handler.removeMessages(what);
}
  1. 通过弱引用来持有当前Activity
public class XXX extends AppCompatActivity {
    private TestHandler mHandler;
    /***/
    private static class TestHandler extends Handler {
        //持有弱引用MainActivity,GC回收时会被回收掉.
        private WeakReference mActivity;
        public TestHandler(XXX activity) {
            mActivity = new WeakReference<>(activity);
        }
 
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
        }
    }
}

你可能感兴趣的:(Android-消息机制)