1.内存泄漏根本原因
内存泄漏的根本原因是:长生命周期的对象持有短生命周期的对象,短生命周期的对象就无法及时释放。
2.Handler错误使用
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Toast.makeText(MainActivity.this, "测试", Toast.LENGTH_SHORT).show();
}
};
Handler允许我们发送延时消息,如果在延时消息未处理完,而此时Handler所在的Activity被关闭,但因为上述Handler用法则可能会导致内存泄漏。首先,Handler是以内部类的形式被创建,那么它将隐性持有外部类的对象,而且,在Toast中还可以MainActivity.this方式显性持有了MainActivity的对象,那么,在延时消息未处理完时,Handler无法释放外部类MainActivity的对象,从而导致内存泄漏产生。
3.Handler正确用法
package com.yds.jianshu.mobile;
import android.app.Activity;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import java.lang.ref.WeakReference;
public class MainActivity extends AppCompatActivity{
private static final String TAG = "[MainActivity]";
private MyHandler handler;
private TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
}
private void initData(){
tv = findViewById(R.id.text);
handler = new MyHandler(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
if (handler!=null){
handler.removeCallbacksAndMessages(null);
}
}
private static class MyHandler extends Handler{
private WeakReference<MainActivity>reference;
public MyHandler(MainActivity activity){
reference = new WeakReference<>(activity);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
MainActivity activity = reference.get();
if (activity!=null){
Toast.makeText(activity, "测试", Toast.LENGTH_SHORT).show();
activity.tv.setText("测试");
}
}
}
}
上面代码中,通过弱引用来协助Handler的调用
reference = new WeakReference<>(activity);
4. Runnable错误用法
private Runnable mRunnable = new Runnable() {
@Override
public void run() {
}
};
一样的道理,该使用方法是创建了一个内部类,内部类隐性持有外部类对象的引用,如果Activity结束,Runnable里面的任务没有处理完,则不会释放Activity的引用,则Activity无法被回收,造成内存泄漏。
5.Runnable正确用法
private static class MyRunnable implements Runnable{
WeakReference<MainActivity> reference;
public MyRunnable(MainActivity activity){
reference = new WeakReference<>(activity);
}
@Override
public void run() {
MainActivity activity = reference.get();
}
}
总结
- 如果直接new一个Handler,则Handler是一个非静态内部类,它隐性地持有外部类的对象。如果外部类需要结束,但消息队列中还有消息未处理完,则Handler不会释放外部类的对象,从而造成内存泄漏。
- 如果直接new一个Runnable,Runnable也是一个非静态内部类,它隐性地持有外部类的对象,如果外部类需要结束,但Runnable还有任务未处理完,则Runnable不会释放外部类的对象,从而造成内存泄漏。