Handler(二)

259 阅读2分钟

这是我参与11月更文挑战的第10天,活动详情查看:2021最后一次更文挑战

在上一章我们简单的介绍了handler的用法,包括message的传递和子线程通知主线程更新UI,接下来介绍一下常用的api和内存泄漏的问题。

1.常用api

    Message message = Message.obtain();
    //发送消息
        new Handler().sendMessage(message);
    //发送一个延时1s的消息
        new Handler().sendMessageDelayed(message, 1000);
    //发送一个带标记的消息(内部创建了message,并设置msg.what = 0x1)
        new Handler().sendEmptyMessage(0x1);
    //发送一个带标记的延时1s的消息
        new Handler().sendEmptyMessageDelayed(0x1, 1000);
    //发送一个延时1秒的消息(第二个参数为:相对系统开机时间的绝对时间,而SystemClock.uptimeMillis()是当前开机时间)
        new Handler().sendMessageAtTime(message, SystemClock.uptimeMillis() + 1000);

2.handler使用避免内存泄露

为什么就会产生内存泄漏呢?

内存类会隐式的持有当前类的外部引用,Handler是非静态内部类持有当前Activity的隐式应用,Handler没有被释放的时候,Activity也不可能被释放,当GC回收这个Activity时,发现有一个正在使用的对象持有他的引用,无法释放内存,就会发现内存泄漏。

(1)怎么使用可能会导致内存泄漏

public class MainActivity extends AppCompatActivity {
 
    final Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
        }
    };
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
            }
        }, 1000 * 60);
    }
}

activity被执行时,要发送的消息要在主线程中延迟一分钟发送,这个消息持有一个handler的引用, 但是它是由内部类创建的,还在隐式的持有着activity引用,不能正常释放而产生内存泄漏。

(2)怎么避免内存泄漏

public class MainActivity extends AppCompatActivity {
 
    private static class MyHandler extends Handler{
       
        private final WeakReference<MainActivity> mAct;
        public MyHandler(MainActivity mainActivity){
            mAct =new WeakReference<MainActivity>(mainActivity);
        }
        @Override
        public void handleMessage(Message msg) {
            MainActivity mainAct=mAct.get();
            super.handleMessage(msg);
            if(mainAct!=null){
            
            }
        }
    }
    private static final Runnable myRunnable = new Runnable() {
        @Override
        public void run() {
        
        }
    };
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        MyHandler myHandler=new MyHandler(this);
        myHandler.postDelayed(myRunnable, 1000 * 60 );
    }
}