Android应用程序的内存被限定在16MB,至少在G1手机上是这样。对于一个手机来说,这已经占用了非常多的内存了,但是对于开发者想要实现的目标而言,这些内存是非常少的。即时你本来就没打算用掉所有的内存,但是你应该尽可能的少用内存,来让其他程序可以保持运行,而不是被系统杀掉。系统在内存里保存的应用程序越多,用户在应用程序之间选择切换的速度就会越快。作为我工作的一部分,我跟踪了Android应用程序内存泄露的情况,发现它们大多数是因为同一个问题:保持了对Context对象的长期的引用。

在Android系统上,很多操作都用到了Context对象,但是大多数都是用来加载和访问资源的。这就是为什么所有的显示控件都需要一个Context对象作为构造方法的参数。在Android应用程序中,你通常可以使用两种Context对象,Activity和Application。当类或者方法需要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结构和它所有的资源。所以,如果你一直保持着对Activity的引用,你占用了很多内存。在你不注意的时候,你很容易就持有对activity的长期引用。
当屏幕方向改变时,默认的,系统会摧毁当前的activity,然后创建一个新的activity,这个新的activity会显示刚才的状态。在这样做的过程中,Android系统会重新加载UI用到的资源。现在假设你的应用程序中有一个比较大的bitmap类型的图片,然而你不想每次旋转时都重新加载它。
保持屏幕旋转,又不让它重新加载,最简单的方法是用静态变量的方法。
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对象的一种情况,你可以在“ Home screen's source code( unbindDrawables()方法)”中看到是如何做的,当activity被摧毁时,设置drawable的回调(引用)为null。令人感兴趣的是,有很多种情况,你会创建出一个泄露context对象的链,它们是糟糕的。它们会很快耗光内存,使你的内存溢出。

有两种简单的方法可以避免由引用context对象造成的内存泄露。最明显的一个方法是,避免context对象超出它的作用范围。上面的例子显展示了静态引用的情况,但是在类的内部,隐式的引用外部的类同样的危险。第二种方法是,使用Application对象。这个context对象会随着应用程序的存在而存在,而不依赖于activity的生命周期。如果你打算对context对象保持一个长期的引用,请记住这个application对象。通过调用Context.getApplicationContext() 或者 Activity.getApplication().方法,你可以很容易的得到这个对象。

总之,要避免由于引用context对象造成的内存泄露,记住以下几点:

不要保持对activity的持久引用(对activity的引用应该和activity本身有相同的生命周期) 尽量使用application代替activity 如果不能控制非静态的内部类的生命周期,尽量在activity中避免有非静态的内部类,在activity中使用静态的类,要对activity保持弱引用。 垃圾回收器并不能保证阻止内存泄露

更多相关文章

  1. Android(安卓)图片缓存防止OutOfMemoryError异常
  2. 强指针和弱指针
  3. Android(安卓)内存管理的相关知识
  4. android 内存泄露原因以及排查和解决方案
  5. android APP性能优化总结
  6. Android中常出现的内存泄漏情况分析
  7. Android里应用程序,应用程序窗口和视图对象之间的关系
  8. Android(安卓)VacantCell缓存
  9. Android内存原理

随机推荐

  1. android json访问php webservice
  2. Android中AsyncTask的简单用法 .
  3. android app 缓存 ---- android 文件缓存
  4. 如何在Android上显示wmf的文件
  5. Android(安卓)中Message,MessageQueue,Lo
  6. 【Android增量升级系列_02】 浅谈Android
  7. Android之Weight属性源码解析
  8. android蜂巢效果、环形菜单、Kotlin影视
  9. 深入了解Android(安卓)任务和进程
  10. 小米:最快11月底或12月初推出 Android 4.0