Android编程中避免内存泄露的方法总结

 更新时间:2014年08月11日 11:36:13   投稿:junjie  
这篇文章主要介绍了Android编程中避免内存泄露的方法总结,本文讲解了最可能造成内存泄露的几个点,并总结出如何应对这些内存泄露,需要的朋友可以参考下

Android的应用被限制为最多占用16m的内存,至少在T-Mobile G1上是这样的(当然现在已经有几百兆的内存可以用了——译者注)。它包括电话本身占用的和开发者可以使用的两部分。即使你没有占用全部内存的打算,你也应该尽量少的使用内存,以免别的应用在运行的时候关闭你的应用。Android能在内存中保持的应用越多,用户在切换应用的时候就越快。作为我的一项工作,我仔细研究了Android应用的内存泄露问题,大多数情况下它们是由同一个错误引起的,那就是对一个上下文(Context)保持了长时间的引用。

在Android中,上下文(Context)被用作很多操作中,但是大部分是载入和访问资源。这就是所有的widget都会在它们的构造函数中接受一个上下文(Context)参数。在一个合格的Android应用中,你通常能够用到两种上下文(Context):活动(Activity)和应用(Application)。活动(Activity)通常被传递给需要上下文(Context)参数的类或者方法:

复制代码 代码如下:

@Override
protected void onCreate(Bundle state) {
  super.onCreate(state);
 
  TextView label = new TextView(this);
  label.setText("Leaks are bad");
 
  setContentView(label);
}

这就意味着那个View有一个对整个活动(Activity)的引用并且对这个活动(Activity)中保持的所有对象有保持了引用;通常它们包括整个View的层次和它的所有资源。因此,如果你“泄露”了上下文(Context)(这里“泄露”的意思是你保持了一个引用并且组织GC收集它),你将造成大量的内存泄露。如果你不够小心的话,“泄露”一整个活动(Activity)是件非常简单的事情。

当屏幕的方向改变时系统会默认的销毁当前的活动(Activity)并且创建一个新的并且保持了它的状态。这样的结果就是Android会从资源中重新载入应用的UI。现在想象一下,你写了一个应用,有一个非常大的位图,并且你并不想在每次旋转时都重新载入。保留它并且每次旋转不重新加载的最简单的办法就是把它保存在一个静态字段上:

复制代码 代码如下:

private static Drawable sBackground;
 
@Override
protected void onCreate(Bundle state) {
  super.onCreate(state);
 
  TextView label = new TextView(this);
  label.setText("Leaks are bad");
 
  if (sBackground == null) {
    sBackground = getDrawable(R.drawable.large_bitmap);
  }
  label.setBackgroundDrawable(sBackground);
 
  setContentView(label);
}

这段代码非常快,同时也错的够离谱。它泄露了当第一次屏幕角度改变时创建的第一个活动(Activity)。当一个Drawable被附加到一个View,这个View被设置为drawable的一个回调。在上面的代码片断中,这意味着这个Drawable对TextView有一个引用,同时这个TextView对Activity(Context对象)保持着引用,同时这个Activity对很多对象又有引用(这个多少还要看你的代码了)。

这个例子是造成Context泄露的最简单的一个原因,你可以看一下我们在主屏幕源码(查看unbindDrawables()方法)中是通过在Activity销毁时设置保存过的Drawable的回调为空来解决这个问题的。更为有趣的是,你可以创建一个context泄露的链,当然这非常的糟糕。它们可以让你飞快的用光所有的内存。

有两种简单的方法可以避免与context相关的内存泄露。最明显的一个就是避免在context的自身的范围外使用它。上面的例子展示了在类内部的一个静态的引用和它们对外部类的间接引用是非常危险的。第二个解决方案就是使用Application Context。这个context会伴随你的应用而存在,并且不依赖Activity的的生命周期。如果你计划保持一个需要context的长生命周期的对象,请记得考虑Application对象。你可以非常方便的通过调用Context.getApplicationContext() 或者 Activity.getApplication()获取它。

总之,为了避免涉及到context的内存泄露,请记住如下几点:

1.不要对一个Activity Context保持长生命周期的引用(一个对Activity的引用应该与Activity自身的生命周期相同)
2.尝试使用应用上下文(context-application)代替活动上下文(context-activity)
3.如果你不能控制它们的生命周期,在活动(Activity)中避免使用不是静态的内部类,使用静态类并且使用弱引用到活动(Activity)的内部。对于这个问题的解决方法是使用静态的内部类与一个弱引用(WeakReference)的外部类。就像ViewRoot和它的W内部类那么实现的。
4.垃圾回收器对于内存泄露来说并不是百分百保险的。

相关文章

  • Android 打开网络上pdf文件

    Android 打开网络上pdf文件

    本文主要介绍了Android打开网络上pdf文件的方法,具有很好的参考价值。下面跟着小编一起来看下吧
    2017-04-04
  • Android滑动事件冲突详解(一)

    Android滑动事件冲突详解(一)

    这篇文章主要为大家详细介绍了Android滑动事件冲突,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-03-03
  • Android编程单元测试实例详解(附源码)

    Android编程单元测试实例详解(附源码)

    这篇文章主要介绍了Android编程单元测试,结合完整实例形式详细分析了Android单元测试的具体步骤与相关技巧,并附带完整实例代码供读者下载参考,需要的朋友可以参考下
    2015-11-11
  • Android自定义九宫格输入框

    Android自定义九宫格输入框

    这篇文章主要为大家详细介绍了Android自定义九宫格输入框,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-06-06
  • 解决android报错:Intel HAXM is required to run this AVD

    解决android报错:Intel HAXM is required to run this AVD

    这篇文章主要介绍了解决android报错:Intel HAXM is required to run this AVD,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-11-11
  • Android 页面多状态布局管理的开发

    Android 页面多状态布局管理的开发

    页面多状态布局是开发中常见的需求,即页面在不同状态需要显示不同的布局,这篇文章主要介绍了Android 页面多状态布局管理的开发,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-10-10
  • Android启动页设置及动态权限跳转问题解决

    Android启动页设置及动态权限跳转问题解决

    在我遇到这个实际问题之前,我一直认为启动页的作用是美化产品,提升软件逼格。但实际上,它更重要的是起到了一个拦截器的作用,这篇文章主要介绍了Android启动页设置以及动态权限跳转,需要的朋友可以参考下
    2022-04-04
  • android开发之蜂鸣提示音和震动提示的实现原理与参考代码

    android开发之蜂鸣提示音和震动提示的实现原理与参考代码

    蜂鸣提示音和震动提示此功能在手机使用中很实用,最近在读zxing项目,学到了不少东西;我们一起来看看他是怎么做的,感兴趣的朋友可以了解下哦
    2013-01-01
  • 8种android 对话框(Dialog)使用方法详解

    8种android 对话框(Dialog)使用方法详解

    这篇文章主要介绍了8种android 对话框(Dialog)使用方法。感兴趣的朋友可以参考一下
    2016-03-03
  • android滑动解锁震动效果的开启和取消

    android滑动解锁震动效果的开启和取消

    在4.0的圆环滑动解锁中,我们点击下去的时候会有震动效果,因为这个控件设置的震动效果没有绑定设置中设置的触摸振动开关来取消振动效果,下边这个例子实现了开启和取消的方法
    2013-06-06

最新评论