- 原因
- 解决办法
- 代码
在写Android App时,一些逻辑不能放在UI线程中,于是可能会用到Handler。
如果直接向下面那样new一个Handler可能会有Warning: This Handler class should be static or leaks might occur.
1 2 3 4 5 6
| private final Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { } };
|
原因
大概就是在Activity finish之后,Message可能依然存在消息队列中。而这个Message有一个对Handler的引用,Handler也有一个对外部类MainActivity的隐式引用。
这些引用在Message被执行前将一直保留,故不被垃圾回收机制回收,从而导致泄露。
解决办法
写一个静态匿名内部类。静态匿名内部类不会持有一个对外部类的隐式引用,因此Activity将不会被泄露。
如果需要在Handler中调用外部Activity的方法,就在Handler中加一个对Activity的WeakReference,这样就不会泄露了。
代码
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
| import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.View;
import java.lang.ref.WeakReference;
public class MainActivity extends Activity { public final MyHandler mHandler = new MyHandler(this);
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() { public void onClick(View v) { Message message = mHandler.obtainMessage(); message.what = 0; mHandler.sendMessage(message); } }); }
public static class MyHandler extends Handler { private final WeakReference<MainActivity> mActivity;
public MyHandler(MainActivity activity) { mActivity = new WeakReference<>(activity); }
public void handleMessage(Message msg) { MainActivity activity = mActivity.get(); if (activity != null) { switch (msg.what) { case 0: break; } } } } }
|