美文网首页
Android常见的内存泄漏

Android常见的内存泄漏

作者: jacky123 | 来源:发表于2016-06-22 00:22 被阅读185次

1. Bitmap使用完忘记回收

因为bitmap实现部分是通过JNI调用了Native方法,GC机制无法正常回收 Bitmap申请的这部分内存空间(API10之前是这样的,之后分配在Heap中,不过为了兼容老版本...显示的调用一下recycled,让对象变为虚引用,也能让GC到来的几率更高);
那Bitmap应该怎样回收呢?

if(bitmap!=null&&!bitmap.isRecycled){
    bitmap.recycled(); //回收bitmap
    bitmap = null;   //使bitmap对象变为虚引用的状态,让GC更快的回收
}

2.万恶的static

被static修饰的变量,生命周期与整个App的生命周期相同,需要谨慎使用它来修饰一些耗费资源过多的实例

private static Drawable sBackground;

@Override
protected void onCreate(Bundlestate){
    super.onCreate(state);
    label.setText("Leaksarebad");
    if(sBackground==null){
        sBackground=getDrawable(R.drawable.large_bitmap);
    }
    label.setBackgroundDrawable(sBackground);
    setContentView(label);
}

这里的sBackground是个静态变量,也就是说就算Activity销毁掉了,他也无法被释放,就导致了内存浪费,当然这还没完... 当Drawable与View绑定之后,Drawable就将View设置为一个回调,由于View中是包含了Context引用的,最终就是 Context发生内存泄露;

注意:Drawable就将View设置为一个回调,是将View引用为一个WeakReference,这边是否真正引起内存泄漏,还需要测试(API23)。

3.Context的引用问题

当然2中也提到了一部分,咱们再看看这里的

btn_hint.setOnClickListener(new View.OnClickListener() {
@Override
    public void onClick(View v) {
        Toast.makeText(MainActivity.this, "Hello", Toast.LENGTH_SHORT).show();
    }
});

是不是很常见,平时可能也是这样写的(将其封装意义一样,只要引用了当前activity),你可能想问,这里有什么问题吗?

问题在于如果用户在Toast消失之前,用户按了返回键,这个Activity就引起了内存泄露,
原因? Toast持有了当前Activity,导致Activity无法被GC销毁

解决方法:让Toast持有ApplicationContext;其实只要不是Layout,Context都可以使用ApplicationContext;

关于Context的tips

  • 在单列模式中,如果用到的Context,应该使用与App的生命周期相同的ApplicationContext.
  • 在非Activity中,正常是不能直接getContext来拿到Context的,获取资源有需要靠Context,这时可以考虑在自己的Application中维护一个全局的Context,供无法直接拿到Context的类使用,省的参数传来传去(视图相关的不建议使用ApplicationContext)

在Application中

private static Context mContext;
public static MyApplication getInstance() { //供外界调用...
    return mApplication;
}

@Override
public void onCreate() {
    super.onCreate(); 
    mContext = getApplicationContext();   
}

4.线程引发的内存泄露

new Thread() {
    public void run() {
        //网络请求
    };
}.start();

在Activity中 新建一个线程,进行网络请求,如果线程未结束,用户按了返回键,同样内存泄露

原因:该Thread是匿名内部类,所以会隐式的持有外部类(这里也就是Activity),Handler内存泄漏也是这个原因,详细可以阅读我的博客:Handler的终结者

解决方式:多种多样; 不使用匿名内部类,或者整个应用维护一个线程池,或者维护一个线程+消息队列+WeakReference,后两种都是让线程不依赖于Activity从而达到避免内存泄露的目的;

5.资源未关闭造成的内存泄漏

对于使用了BroadcastReceiver,ContentObserver,File,Cursor,Stream,Bitmap等资源的使用,应该在Activity销毁时及时关闭或者注销,否则这些资源将不会被回收,造成内存泄漏。

参考资料

相关文章

  • Android内存泄漏检测和定位

    建议阅读Android常见内存泄漏这篇文章,本文的例子来源于文章中的内存泄漏典型例子 内存泄漏检测工具 Profi...

  • Android内存泄漏原因及解决的总结

    分三步说明Android内存泄漏的原因及解决,“内存泄漏与内存溢出的区别”,“引用方式”,“常见引发原因与解决方案...

  • Android-推荐一个检测内存泄漏的库(LeakCanary)

    在Android开发当中,内存泄漏是会影响用户体验的。LeakCanary开源库是一个常见的定位内存泄漏的开源库,...

  • 带你学开源项目:LeakCanary-如何检测 Activity

    OOM 是 Android 开发中常见的问题,而内存泄漏往往是罪魁祸首。为了简单方便的检测内存泄漏,Square ...

  • 科普 - 收藏集 - 掘金

    5 个 Android 开发中比较常见的内存泄漏问题及解决办法 - Android - 掘金在Android开发中...

  • Android 优化

    Android 内存优化内存溢出 , 内存泄漏 , 内存泄漏过多就导致内存溢出 Android 系统垃圾回收机制内...

  • Android 常见内存泄漏

    构造单例的时候尽量别用Activity的引用; 静态引用时注意应用对象的置空或者少用静态引用; 使用静态内部类+软...

  • Android 常见内存泄漏

    一、单例造成的内存泄漏Android的单例模式非常受开发者的喜爱,不过使用的不恰当的话也会造成内存泄漏。因为单例的...

  • Android - 常见内存泄漏

    单例 单例静态对象持有activity引用,且因静态对象生命周期比activity还长,当act被销毁时,单例中的...

  • Android常见内存泄漏

    内存泄漏场景: 静态变量引用非静态内部类/匿名类实例。子线程相关的非静态内部类/匿名内部类引用。Handler导致...

网友评论

      本文标题:Android常见的内存泄漏

      本文链接:https://www.haomeiwen.com/subject/umwgdttx.html