文章目录
标题:什么是android内存泄漏
答: 内存泄漏:长生命周期的对象持有短生命周期的对象,导致短生命周期对象不能被回收
举例
1、单例模式造成内存泄漏
原因:
单例模式生命周期比activity生命周期长,单例模式引用了activity的context,,activity退出的时候,导致activity不能被回收
解决办法:
1、使用 Application 的 context
2、将context的引用方式改为弱引用
代码举例
//使用 Application 的 context
public class Singleton {
private static volatile Singleton instance = null;
private Context context;
private Singleton(Context context) {
this.context = context.getApplicationContext();
}
public static Singleton getInstance(Context context) {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton(context);
}
}
}
return instance;
}
public void function(String param1, String param2) {
context.startActivity(new Intent(context, MainActivity.class));
}
}
//将context的引用方式改为弱引用
public class SingletonWeakReference {
private static volatile SingletonWeakReference instance = null;
private WeakReference<Context> contextWeakReference;
private SingletonWeakReference(Context context) {
contextWeakReference = new WeakReference<>(context);
}
public static SingletonWeakReference getInstance(Context context) {
if (instance == null) {
synchronized (SingletonWeakReference.class) {
if (instance == null) {
instance = new SingletonWeakReference(context);
}
}
}
return instance;
}
public void function(String param1, String param2) {
Context context = (Context) contextWeakReference.get();
if (context != null) {
context.startActivity(new Intent(context, MainActivity.class));
}
}
}
2、非静态内部类,匿名内容类造成内存泄漏
原因:
非静态内部类持有外部类的引用,如果外部类的实例已经结束生命周期,但内部类仍然在执行,就会导致外部类不能被回收。
解决办法:
1、在Activity结束时将反注册,结束倒计时,清空消息,等(broadCastReceiver,TimerTask,handler)
2、使用静态内部类+弱引用
2.1、handler造成内存泄露(归属第二类)
原因:
a、message被Handler send出去的时候,会被加入的MessageQueue中,Looper会不停的从MessageQueue中取出Message并分发执行。但是如果Activity退出的时候,Handler发送的message没有执行完毕。那么Handler就不会被回收,但是由于非静态内部类持有外部类的引用,导致外部类不会被回收
b、handler发送的消息在handler的消息队列中,如果此时activity finish掉,那么消息队列的消息依旧会由handler进行处理
解决办法:
1、在Activity结束时将Handler里面的Message清空
2、使用静态内部类+弱引用
代码举例
//在Activity结束时将Handler里面的Message清空
@Override
protected void onDestroy() {
super.onDestroy();
//将Handler里面消息清空
mHandler.removeCallbacksAndMessages(null);
}
//使用静态内部类+弱引用
private static class MyHandler extends Handler {
private WeakReference<Context> contextWeakReference;
private MyHandler(Context context) {
contextWeakReference = new WeakReference<>(context);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Context context = (Context) weakReference.get();
if (context != null) {
context.startActivity(new Intent(context, MainActivity.class));
}
}
}
3、资源未关闭造成内存泄漏
BraodcastReceiver ,Cursor,Bitmap,io流等资源的使用,应该在Activity销毁时及时关闭或者注销,否则这些资源将不会被回收,造成内存泄漏。
BraodcastReceiver注销注册unregisterReceiver()
io流关闭流InputStream ,OutputStream.close()
数据库游标Cursor关闭游标cursor.close()
Bitmap调用recycle()回收内存,再赋为null
4、WebView造成的内存泄漏
@Override
protected void onDestroy() {
super.onDestroy();
// 先从父控件中移除WebView
mWebViewContainer.removeView(mWebView);
mWebView.stopLoading();
mWebView.getSettings().setJavaScriptEnabled(false);
mWebView.clearHistory();
mWebView.removeAllViews();
mWebView.destroy();
}
内存泄漏延伸:Java中四种引用类型
强软弱虚
强引用:即使内存不足,JVM宁愿抛出OOM,也不会去回收。
软引用:当内存不足,会触发JVM的GC,如果GC后,内存还是不足,就会把软引用的包裹的对象回收,也就是只有在内存不足,JVM才会回收该对象。
弱引用:只要发生GC,就会被回收
虚引用:
//下面先来看看如何创建一个软引用:
SoftReference<Student>studentSoftReference=new SoftReference<Student>(new Student());
//软引用就是把对象用SoftReference包裹一下,当我们需要从软引用对象获得包裹的对象,只要get一下就可以了:
SoftReference<Student>studentSoftReference=new SoftReference<Student>(new Student());
Student student = studentSoftReference.get();
System.out.println(student);