原文来自Android SDK文档中的 docs/resources/articles/avoiding-memory-leaks.html
android应用,堆内存大小限制为16MB(至少在T-Mobile G1上是这样)。 对手机而言, 这已经是相当大一部分内存,但对某些开发者而言16MB太少了。 就算不准备使用全部的16MB内存, 至少也应用使用尽可能少的内存,从而避免其他应用因为内存不足而被杀死。Android平台上, 内存中的应用越多, 用户切换应用的速度就可以越快。在我的工作中, 我遇到过Android应用内存泄漏问题大部分可以归结为同样一个错误: 长时间持久Context对象的引用。
Android平台上, Context用作大量的操作, 但总的来说主要是用于加载和访问资源。这也正是所有的Widget的构建方法需要一个Context参数的原因。 对普通Android应用来说, 有两种Contxt:Activity Context和Application Context。 通常会将前者传递给需要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泄漏(泄漏即你引用这个Context,导致GC不能回收它), 会引用大量内存的泄漏。如果不注意, 很容易泄漏整个Activity使用的内存。
当改变屏幕方向时,缺省情况下系统会销毁当前Activity(会保存其状态),然后重新生成一个Activity实例。这个过程中, Android会重新加载应用的UI资源。想象一下, 你写了一个使用了大图片的应用, 你不想每当改变屏幕方向时就要重新加载这张大图片。 (注:显然加载大图片会非常耗时)。 最简单的办法就是用一个静态成员变量保存这张图片的引用,避免每次转动屏幕时重新加载:
@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的一个回调接口。 在上面的代码中, sBackground持有label的引用, 而label又持有Activity(即Activity Context)的引用, 从而持有非常多的引用(与具体代码相关)。
上面的例子是Context相关的内存泄漏最简单一种场景。 可以在Home screen's source code 中找到解决办法(见 unbindDrawables()方法): 当Activity被销毁时, 将保存起来的drawable的回调接口置为null。 有趣的是, 某些场景下会出现Context泄漏链(原文a chain of leaked contexts), 相当糟糕。 这些场景中内存会很快耗尽。 (注意, Context泄漏链没那么有趣, 但也不算太糟糕。 内存很快耗尽意味着问题容易暴露和复现)。
有两个简单的方法避免Context相关的内存泄漏。 最直接办法是避免在Context对象逃逸到的其作用域(或生命周期)外。 上面的例子中展示了静态引用是如何引发问题的,实际上内部类隐含持有外部对象的引用, 同样非常危险。 另外一个办法就是使用Application Context. 这种Context生命周期与应用所在进程的生命周期一样长, 而不依赖于Activity的生命周期无关。 当需要持有一个长生命周期的、而且使用Context的对象时, 请使用这个Application Context。 可以通过调用Context.getApplicationContext()或Activity.getApplication()来获取这个Context。
总之, 想要避免Context相关的内存泄漏, 请记住以下几点:
- 不要长期持有Activity(Context)的引用。 对Activity的引用, 其生命周期应当与Actvity本身的生命周期相同。
- 尽量使用Application Context而不是Activity Context
- 如果不能控制它们的生命周期, 则要避免在Activity中使用非静态的内部类(原文non-static inner classes)。 可以使用一个嵌套类(原文static inner classes), 并且持有对外部Activity对象的弱引用(weak reference)。 这种方法可参考ViewRoot及其嵌套类W
- 垃圾回收器并不是保证避免内存泄漏
分享到:
相关推荐
An Android console view, which allows you to log text using static calls, to easily debug your application, whilst avoiding memory leaks. Usage Include Console anywhere in your layout: then ...
Chapter 12, Audio in Game Development, explains how to add sound and music effects to games, and avoiding memory leaks while playing sounds. Chapter 13, Tips and Tricks, has some neat tips and tricks...
【避免垃圾邮件】 在互联网发展的历程中,从最初的物理学数据分享平台,到如今成为文化、教育,特别是商业生活的核心部分,网络已经变得无处不在。数以百万计的用户现在通过网页进行各种金融交易,包括购物、预订...
C++ Gotchas Avoiding Common Problems in Coding and Design 英文epub 本资源转载自网络,如有侵权,请联系上传者或csdn删除 本资源转载自网络,如有侵权,请联系上传者或csdn删除
气候变化研究中关于温度极端指数的处理方法Using a Monte Carlo simulation, it is demonstrated that percentile-based temperature indices computed for climate change detection and monitoring may contain ...
Android MVP Architecture A basic sample android application to understand MVP in a very simple way. Just clone, build, run ...avoiding Activity leaks by releasing the view when it's no longer needed ,B
Avoiding Read While Write Errors When In-Software Flash
在IT领域,尤其是在数据存储与保护的技术探讨中,《Avoiding the Disk Bottleneck in the Data Domain Deduplication File System》一文提供了深入的见解和技术解决方案,旨在优化基于磁盘的重复数据删除...
ARDUINO_OBSTACLE_AVOIDING_CAR 避开基于arduino的车辆的障碍在此存储库中,我仅给出了避开arduino基础车辆的障碍物的源代码。 您可以单击链接以获取源代码。 链接:
A note on cover-avoiding properties of finite groups,刘建军,郭秀云,A subgroup H of a group G is said to be a CAP*-subgroup of a group G if, for any non-Frattini chief factor K/L of G, we have HK=HL...
- **Memory Profiling**: Use memory profiling tools to identify memory leaks and excessive object creation. - **Memory Management**: Implement strategies to free up memory when it is no longer needed. ...
当构建使用动态VI的可执行文件时,必须确保在LabVIEW Application Builder规范的'always include'部分指定动态VI的名称。不这样做会导致问题,表现为LabVIEW应用程序将无法加载您的动态Vl,并将引发各种错误或导致...
自回避行走(Self-Avoiding Walk,简称SAW)是一种在数学、物理和化学领域广泛研究的统计力学模型。在该模型中,一个行走者在二维或三维空间中移动,但不能与其之前走过的路径重叠,即行走的每一步都不能与之前的...
是讲述安全编程的好书!!!
1Avoiding AVX-SSE Transition PenaltiesTransitioning between 256-bit Intel:registered: AVX instructions and legacy Intel:registered: SSE instructions within a program may cause performance penalties ...
An-OARSMan: An Obstacle-Avoiding Rectilinear Steiner Tree Algorithm with Good Length Performance,胡昱,经彤,Routing is one of the important steps in VLSI/ULSI physical design. The rectilinear ...
【Server Virtualization: 避免I/O陷阱】 在服务器虚拟化的过程中,企业通常能体验到应用程序部署的简化和整体服务器利用率的提升。然而,如果不考虑相应的存储I/O性能调整,这种快速整合可能会导致性能影响的隐患...
Topics covered include pointer arithmetic, dereferencing, and common pitfalls like dangling pointers and memory leaks. The chapter also provides practical tips for working with pointers, including ...