问题重现
编写以下代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class OOMHandlerActivity extends Activity {
private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); ((EditText) findViewById(R.id.oom_handler_edit_text)).setText("aaaas"); } };
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_oom_handler); mHandler.sendEmptyMessageDelayed(1, 1000 * 60); } }
|
使用Android Studio自带的Profile进行监控,打开OOMHandlerActivity页面,然后返回上一个页面。Dump内存后,会出现以下提示:
原因分析
依据Handler的实现原理,我们可知,内存泄漏的引用链如下:
主线程 —> threadlocal —> Looper —> MessageQueue —> Message —> Handler —> Activity
解决办法
对于Handler的使用技巧,我们应该:
- 使用静态内部类的方式
- 如果需要处理宿主,则通过弱引用的传入进来
- Activity生命周期结束时,释放Handler资源
参考以下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| package com.lqd.androidpractice.oom.handler;
import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.widget.TextView;
import com.lqd.androidpractice.R;
import java.lang.ref.WeakReference;
public class OOMHandlerRightActivity extends Activity { 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) { OOMHandlerRightActivity activity = (OOMHandlerRightActivity) reference.get(); if (activity != null) { activity.mTextView.setText(""); } } }
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_oom_handler); mTextView = (TextView) findViewById(R.id.textview); mHandler.sendEmptyMessageDelayed(1, 1000 * 60); }
@Override protected void onDestroy() { super.onDestroy(); mHandler.removeCallbacksAndMessages(null); } }
|
参考