您的位置:首页 > 移动开发 > Android开发

Android 常见的几种内存泄漏 - Handler

2017-06-09 13:18 218 查看
Handler的使用造成的内存泄漏问题应该说最为常见了,平时在处理网络任务或者封装一些请求回调等api都应该会借助Handler来处理,对于Handler的使用代码编写一不规范即有可能造成内存泄漏,如下示例:

public class MainActivity extends AppCompatActivity {
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
//...
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
loadData();
}
private void loadData(){
//...request
Message message = Message.obtain();
mHandler.sendMessage(message);
}
}


这种创建Handler的方式会造成内存泄漏,由于mHandler是Handler的匿名内部类的实例,所以它持有外部类Activity的引用,我们知道消息队列是在一个Looper线程中不断轮询处理消息,那么当这个Activity退出时消息队列中还有未处理的消息或者正在处理消息,而消息message持有mHandler实例的引用,mHandler又持有Activity的引用,所以导致该Activity的内存资源无法及时回收,引发内存泄漏。

那怎么样才可以避免这中问题呢,这里提供两个解决方案。这个问题是由于当Activity被销毁时发现引用它的Handler还在,从而导致了GC无法回收Activity。那么最简单最直接的方法是在Activity的OnDestory方法中移除所有的消息和回调即清空队列,MessageQueue被释放 从而使Handler得到释放,这时GC就能正常回收被销毁的Activity了。所以这种解决方案方法如下:

@Override
protected void onDestroy() {
super.onDestroy();
mHandler.removeCallbacksAndMessages(null);
}


这个解决方案我们忽略了消息队列的作用。由于Handler对于Activity的引用导致GC无法回收Activity,我们直接暴力的把消息队列清空了,那如果需要这些处理消息队列中的消息呢?这就需要用到我们第二个解决方案:弱引用。其原理就是让所有在handler里面使用的对象都变成弱引用,目的就是为了可以在Android回收内存的时候,可以直接回收掉。

public class MainActivity extends AppCompatActivity {
private MyHandler mHandler = new MyHandler(this);
private TextView mTextView ;
private static class MyHandler extends Handler {
private WeakReference<Context> reference;
public MyHandler(Context context) {
reference = new WeakReference<>(context);
}
@Override
public void handleMessage(Message msg) {
MainActivity activity = (MainActivity) reference.get();
if(activity != null){
activity.mTextView.setText("");
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = (TextView)findViewById(R.id.textview);
loadData();
}
private void loadData() {
//...request
Message message = Message.obtain();
mHandler.sendMessage(message);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息