Android ~ Android内存泄漏


标题:什么是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);  

文章由个人搜集资料总结,如有错误,欢迎指证!

  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值