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保持弱引用。
垃圾回收器并不能保证阻止内存泄露
分享到:
相关推荐
Android webview 内存泄露的解决方法 最近在activity嵌套webview显示大量图文发现APP内存一直在涨,没法释放内存,查了很多资料,大概是webview的一...这样动态生成webview就能避免内存泄漏,可是这样会导致部分机型的w
Android处理内存泄漏的代码例子。用于演示避免内存泄漏的几种方法,包括:关闭游标、重用适配、回收图像、注销监听、释放引用。
如何高效避免Android内存泄露,文档时根据我多年的Android经验编写而成,希望对您有所帮助。
Android应用程序如何避免内存泄漏以及如何检查泄漏原因
android的内存泄露问题,教你如何避免内存泄露 优化程序
1.内容 本文档包含如下内容: 如何确定App存在内存泄露 如何定位App的内存泄露位置 怎样避免内存泄露
Handler对象中使用匿名内部类或非静态内部类正确地释放消息避免内存泄漏或增加Native内存,在Android中,Handler对象通常会被用来在主线程(UI线程)中处理消息,以更新UI界面。当我们在Handler对象中使用匿名内部类...
本文主要介绍Android中Context引起的内存泄露的问题,这里对Context的知识做了详细讲解,说明如何避免内存泄漏的问题,有兴趣的小伙伴可以参考下
库存android活动的rx绑定&片段生命周期,避免内存泄漏
Android 内存溢出和内存泄漏的问题 在面试中,经常有面试官会问“你知道什么是内存溢出?什么是内存泄漏?怎么避免?”通过这篇文章,你可以回答出来了。 内存溢出 (OOM)是指程序在申请内存时,没有足够的内存空间...
怎样避免内存泄露 使用procrank查看进程内存 procrank 命令可以获得当前系统中各进程的内存使用快照,这里有PSS,USS,VSS,RSS。我们一般观察Uss来反映一个Process的内存使用情况,Uss 的大小代表了只属于本进程...
摘要Android 内存泄漏总结 内存管理的目的就是让我们在开发中怎么有效的避免我们的应用出现内存泄漏的问题。内存泄漏大家都不陌生了,简单粗俗的讲,就是该被释放
什么是内存泄漏?造成内存泄漏的原因?如何解决内存泄漏?以及如何避免内存泄漏等。。。
作为我的一项工作,我仔细研究了Android应用的内存泄露问题,大多数情况下它们是由同一个错误引起的,那就是对一个上下文(Context)保持了长时间的引用。 在Android中,上下文(Context)被用作很多操作中,但是大...
LeakCanary是适用于Android的可靠内存泄漏检测库。 它通过对Android Framework内部的深入了解,可以有效地检测泄漏并缩小每次泄漏的原因。 这有助于开发人员避免并显着减少OutOfMemoryError(OOM)崩溃。 内存泄漏是...
android中用getApplicationContext()会不会避免某些内存泄漏问题? RT,在android开发中,如果在使用context的地方全部用getApplicationContext()会不会避免某些内存泄漏问题? 首先,Activity的Context和...
Android的内存管理-SoftReference的使用、Android垃圾回收实质内容解析、如何避免Android内存泄露等
【Android程序优化,避免内存泄露】- [实战一]:避免内存泄露的最后一道墙,使用leakcanary分析程序中的内存泄露。 博文地址:http://blog.csdn.net/zxt0601/article/details/51010174