上周做一个流量传感器的项目,基本功能是通过BLE实现主界面实时读取设备的数据,其他界面也有读写命令的操作,由于传感器不支持异步的读写操作,所以不同界面的切换需要确保先停止其他界面的读写操作。这部分功能我是用Handler异步更新机制来实现。
用到的功能点:
1、使用Handler延迟发送消息功能,实现一段时间后执行一个操作。
2、使用Handler移除消息发送功能,实现移除一个或多个操作。
套路1:如何正确的使用Handler,不容易发生内存泄露。
小白使用Handler:
public class MainActivity extends Activity{
//...todo....
public Handler mHandler=new Hander{
@override
public void handlerMessage(Message msg){
switch(msg.what){
case XXX:
//访问外部类的成员和方法,做一些操作
break;
}
}
}
//....todo...
但是呢,小白发现Lint检测时会提示这么一句话 : This Handler class should be static or leaks might occur。意为handler应用static修饰否则容易发生内存泄漏。
于是乎,小白就把Handler修改为static,但是发现Handler里面用到的外部类的成员和方法都要声明为static才能被使用。这个时候,小白就直接忽略这个Lint,无奈的等待随时可能发生的内存泄露。
(同一个线程下的handler共享一个looper对象,消息中保留了对handler的引用,只要有消息在队列中,那么handler便无法被回收,如果handler不是static,那么使用Handler的Service和Activity就也无法被回收,即便它们的ondestroy方法被调用。这就可能导致内存泄露。当然这通常不会发生,除非你发送了一个延时很长的消息。)
小强使用Handler:
机智的小强,首先自定义一个继承Handler的静态内部类,然后对Handler依赖的外部Activity使用了弱引用,不仅能够不影响Activity的正常回收而且能够方便地使用该activity实例获取其字段和方法,无需修改为static。代码如下:
public class MainActivity extends Activity{
//....todo...
static class MyHandler extends Handler {
WeakReference<MainActivity> mActivity;
MyHandler(MainActivity activity) {
mActivity = new WeakReference<MainActivity>(activity);
}
@Override
public void handleMessage(Message msg) {
MainActivity activity = mActivity.get();
switch (msg.what) {
case 0:
activity.doSomethings();
break;
}
}
};
MyHandler mHandler = new MyHandler(MainActivity.this);
//....todo...
}