GC ROOT static HandlerCenter.mHandlerList
-- Android removeCallbacksAndMessages(null)不起作用; handler.removeCallbacks(null)不起作用;
调用handler.removeCallbacksAndMessages(null);可以清空当前handler的所有回调和所有消息。想当然的认为handler.removeCallbacks(null)可以清空所有回调,实则不然。
handler.removeCallbacks(null)不会移除任何回调。因为已经处于运行的runnable包含在message中已经移交给handler进行处理了,而Handler.removeCallbacks(Runnable r)只能移除未运行的runnable,所以导致无法停止runnbale的运行,最后失效。
handler.removeCallbacksAndMessages(null):
Remove any pending posts of callbacks and sent messages whose obj is token. If token is null, all callbacks and messages will be removed.
@Override
protected void onDestroy() {
if (handler != null && handler.getLooper() == Looper.getMainLooper()){
handler.removeCallbacksAndMessages(null);
}
super.onDestroy();
}
if (myHandler != null) {
myHandler.removeCallbacksAndMessages(null);
}
- 解决办法
1.最直接的思路就是避免使用非静态内部类。使用Handler的时候,放在一个新建的文件中来继承Handler或者使用静态的内部类来替代。静态内部类不会隐含的持有外部类的引用,因此这个activity也就不会出现内存泄漏问题。
2.如果你需要在Handler内部调用外部Activity的方法,你可以让这个Handler持有这个Activity的弱引用,这样便不会出现内存泄漏的问题了。
3.另外,对于匿名类Runnable,我们同样可以设置成静态的,因为静态内部类不会持有外部类的引用。
4.注意:如果使用Handler发送循环消息,最好是在Activity的OnDestroy方法中调用mLeakHandler.removeCallbacksAndMessages(null);移除消息。(这不是解决内存泄漏的方法)
5.两种解决办法如下:
a.弱引用(WeakReference)
public class SampleActivity extends Activity {
/**
* Instances of static inner classes do not hold an implicit
* reference to their outer class.
* 弱引用的方式
*/
private static class MyHandler extends Handler {
private final WeakReference<SampleActivity> mActivity;
public MyHandler(SampleActivity activity) {
mActivity = new WeakReference<SampleActivity>(activity);
}
@Override
public void handleMessage(Message msg) {
SampleActivity activity = mActivity.get();
if (activity != null) {
//to Something
}
}
}
b.静态
//定义成static的,因为静态内部类不会持有外部类的引用
private final MyHandler mHandler = new MyHandler(this);
private static final Runnable sRunnable = new Runnable() {
@Override
public void run() {//to something}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mHandler.postDelayed(sRunnable, 1000 * 60 * 10);
finish();
}
}
removeCallbacks只能停止处于即将运行状态的messages,这里messages里面包含就是Runnables,如果Runnbale已经启动start(),则removeCallbacks是无法停止的。