本文转载自:http://blog.csdn.net/xiwenhec/article/details/50154279
以前在写代码的时候,对于一些警告信息不是很在意,大致看了一下,自己知道就行了,有时候烦了就干脆屏蔽掉算了,今天我在使用handler的时候看了一下,这个感觉这个警告还是很重要的,于是就看了一下警告的出现可能出现问题的情景。
什么意思呢?大致的意思就是说Handler被声明成了一个内部类,这可能会阻止垃圾回收机制对它所持有的外部类的回收。但是,如果这个Handler所使用的不是主线程的Looper或者MessageQueue的话就不会有这个问题了。注意:如果是主线程的话,就有可能发生内存泄露的情况。
好了,我们知道了问题可能发生的环境,但是还不知道问题发生的原因
这里我们首先说一下:
内存泄露和内存溢出的区别:
很简单顾名思义,所谓泄露就是用一点少一点,什么意思呢?当我们在使用完某个对象时,如果这个对象所占据的内存不及时的别释放,这就可能发生了内存越来越少的情况,最后可能就没了,这就是内存泄露。内存溢出:溢出就是太多了,很显然不是可用内存太多了,而是我们在执行某个操作的时候需要的内存,超过了应用的分配内存,这就是内存溢出。
说了这个么多,我们来分析一下Handler为什么会发生内存泄露呢,原因是应为我们的handler是作为一个内部类被声明的,这个handler就会持有外部类的引用,如果在我们的handler关联的MessageQueue还有消息没有处理,那么垃圾回收器就无法回收这个使用handler的Activity,这就可能是发生内存泄露了。也就是说如果我们在这个主线程的消息队列中有一个延时很长的消息时就有可能发生着中问题。
既然可能有问题,那我们就要解决:
上面的英文也说了:就是说声明称一个static 的内部类,持有外部类的weakReference,在内部类中使用外部类传递过来的weakReference的成员。
public class MainActivity extends Activity {
private TextView mTextView;
private Handler mHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = (TextView)findViewById(R.id.textview);
mHandler = new MyHandler(this);
}
/**
*测试方法
*/
public void executeTest(View v){
mHandler.sendEmptyMessage(0x110);
}
static class MyHandler extends Handler{
WeakReference<MainActivity> mActivity;
public MyHandler(MainActivity activity) {
mActivity = new WeakReference<MainActivity>(activity);
}
@Override
public void handleMessage(Message msg) {
MainActivity mainActivity = mActivity.get();
if(msg.what==1){
mainActivity.mTextView.setText("执行正确");
}
}
}
}
有人说了,这么麻烦,有没有其他的解决方法呢,网上也有这一种方法,提供给大家参考
private Handler mHandler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
// TODO Auto-generated method stub
return false;
}
});
使用这种方式也不会出现内存泄露的警告,有兴趣的可以分析一下哦。。。。