在多线程操作中,handler
会使用的非常多,但是每次使用handler
你有没有考虑内存泄漏的问题。
如果你使用handler
进行操作时,你会发现出现以下提示
This Handler class should be static or leaks might occur (anonymous android.os.Handler)
这样的提示。翻译:
由于此Handler被声明为内部类,因此可能会阻止外部类被垃圾回收。 如果Handler使用Looper
或MessageQueue
作为主线程以外的线程,则没有问题。 如果Handler
正在使用主线程的Looper或MessageQueue
,则需要修复Handler
声明,如下所示:将Handle
r声明为静态类; 在外部类中,实例化外部类的WeakReference
,并在实例化Handler时将此对象传递给Handler; 使用WeakReference
对象对外部类的成员进行所有引用。
警告原因:handler没有设置为静态类,声明内部类可能会阻止被GC回收,从而导致内存泄漏
那么为什么会造成内存泄漏呢。 首先来说下什么是内存泄漏 内存泄漏(Memory Leak):指的是程序已经动态分配的堆内存由于某种原因程序未释放或者无法释放,造成系统资源浪费,会造成程序运行缓慢甚至系统崩溃等严重后果。 问题代码:
public class MainActivity extends AppCompatActivity {
private Handler mHandler = new Handler();
private TextView mTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = (TextView) findViewById(R.id.tv);
//模拟内存泄漏
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
mTextView.setText("yiyi");
}
}, 1000);
}
}
从上面问题代码,可以看出这里通过内部类方式创建handler
,而在java中,非静态内部类会持有外部类的引用,这里的postDelayed
是一个延迟处理消息,将一个handler装入到message中,将消息放进消息队列messageQueue
由Looper
进行取消息进行处理。如果此时activity要退出了,想要调用destroy
销毁,但是此时Looper正在处理消息,Looper
的生命周期明显比activity长,这将使得activity无法被GC
回收,最终造成内存泄漏。并且此时handler还持有activity的引用,也是造成内存泄漏的一个原因(不是根本原因)。
但是我觉得真正
handler
造成内存泄漏的根本原因是生命周期比activity长,比如TextView
也是内部类创建的,那么它怎么没有造成内存泄漏,它也持有外部类Activity
的引用,根本原因是它的生命周期比Activity短,Activity销毁时候,它可以被GC
回收
当handler
有没有处理的消息或者正在处理消息,此时Handler的生命周期明显比Activity
长,GC持有Activity与handler两者的引用,导致Activity
无法被GC
回收,造成内存泄漏。而handler
是不是内部类,并不是造成内存泄漏的根本原因。
将Handler的子类设置成 静态内部类,并且可加上 使用
WeakReference
弱引用持有Activity
实例 原因:弱引用的对象拥有短暂的生命周期。而垃圾回收器不管内存是否充足都会回收弱引用对象。
public class HandlerActivity extends AppCompatActivity {
private static class MyHandler extends Handler {
private final WeakReference<HandlerActivity> mActivity;
public MyHandler(HandlerActivity activity) {
mActivity = new WeakReference<HandlerActivity>(activity);
}
@Override
public void handleMessage(Message msg) {
HandlerActivity activity = mActivity.get();
if (activity != null) {
}
}
private final MyHandler mHandler = new MyHandler(this);
private static final Runnable mRunnable = new Runnable() {
@Override
public void run() { }
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mHandler.postDelayed(mRunnable, 1000 * 60 * 1);
finish();
}
}
只需在Activity
的onDestroy()
方法中调用mHandler.removeCallbacksAndMessages(null)
;就行了。
@Override
protected void onDestroy() {
super.onDestroy();
if(handler!=null){
handler.removeCallbacksAndMessages(null);
handler = null;
}
}