以下是对Android SDK 一篇文章的简单翻译,原文地址为:
http://developer.android.com/resources/articles/avoiding-memory-leaks.html
Andriod应用程序是运行在linux上的dalvik虚拟机,其可分配的堆内存有一个限制,如T-moblie G1为16MB。对手机来说,16MB算是很多了,但对一些开发者来说是太少了。因此,尽管你可能不打算用光这些内存,你也应该尽量用最少的内存,以让其它应用程序不因为系统内存过低而被系统给强制杀掉。在Android里,越多的应用可以在内存里保持,对用户来说,就可以更快地在各个应用之间切换。
Android应用里一个最常见的内存泄露例子是: 保持对一个Context对象的长引用(Keeping a long-lived reference to a 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);
}
这意味着views有一个指向整个activity的引用,同时可以引用到activity所持有的任何资源,比如整个view层次结构和它所有的资源。因此,如果泄露了Context对象(泄露指持有一个指向Context对象的引用而阻止内存垃圾回收器GC来回收它),将会泄露很多内存。 如果不小心的话,泄露整个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);
}
以上代码确实运行很快,但是非常错误的,其泄露了在第一次屏幕方向切换前创建的activiy对象。当一个Drawable对象连接到一个view时,view会被设置为Drawable对象的callback。对以上代码,drawable对象将有一个指向TextView的引用,而TextView自身有一个指向activity(Context)的引用,而activity将引用到非常多的其它资源(取决于你的代码实现)。
此示例是一种最简单的泄露Context对象的案例。 你可以在
Home screen's source code
(查找unbindDrawables方法)看到我们是如何规避此问题的。
即:当activity被摧毁时,设置保存的drawable对象的callback为null。
有意思的是,有一些情况你可能会创建一系列的Context泄露,这是相当糟糕的,会使你很快地用光内存。
如何避免呢? 有两种简单的方式来避免Context相关的内存泄露。最明显的一种是避免将Context对象传出其自身的作用域。上面的示例显示了静态引用的方式,其实内部类及其隐式地引用外部类也是同样危险的。第二种方式是使用Application context对象。 Application context将会一直存在,只要应用程序在存活状态,且不依赖于activity的生命周期。 如果你打算保持一个需要context的长期存活的对象,那就使用application对象。其可以很容易地通过
Context.getApplicationContext()
or Activity.getApplication()
得到。
总之, 要避免Context相关的内存泄露,牢记以下几点:
1. 不要保存一个指向activity context的长期存活的引用(指向一个acitivy的引用应该和该activity拥有同样的生命周期)。
2. 使用application context对象来代替acitivity context对象。
3. 如果不能控制activity里的非静态内部类的生命周期的话,避免使用之。 尽量使用静态内部类,在其内部持有指向activity的弱引用(weak reference)。如ViewRoot及其W内部类示例。
4. 垃圾内存回收器并不能保证防止内存泄露。
分享到:
相关推荐
Android webview 内存泄露的解决方法 最近在activity嵌套webview显示大量图文发现APP内存一直在涨,没法释放内存,查了很多资料,大概是webview的一个BUG,引用了activity导致内存泄漏,所以就尝试传递...
本示例代码着重展示了如何避免Android应用中的内存泄漏,主要包括五个关键方面:关闭游标、重用适配器、回收图像、注销监听器以及释放引用。下面将详细解释这些方法。 1. 关闭游标: 在Android数据库操作中,游标是...
内存泄露在Android开发中是一个非常重要的问题,因为它可能导致应用程序运行缓慢、消耗过多资源甚至崩溃。Android Studio提供了多种工具帮助开发者检测和解决内存泄露,其中包括Memory Profiler和LeakCanary。 ...
本文将深入探讨Android内存泄漏的检测和排查方法,并通过一个锁屏内存泄漏的例子进行具体分析。 首先,我们需要理解什么是内存泄漏。在计算机科学中,内存泄漏是指程序在申请内存后,无法释放已不再使用的内存空间...
在Android开发中,Context...总之,理解Context的作用和生命周期,以及在不同场景下如何正确使用,是避免Android内存泄露的关键。同时,保持良好的编程习惯,及时释放不再使用的资源,可以显著提升应用的性能和稳定性。
2. 单例模式:单例中持有Context引用,若不妥善处理,可能导致内存泄露。 3. 内存泄漏的监听器:如注册了BroadcastReceiver、ContentObserver等,若忘记在合适时机注销,将导致内存泄露。 4. 异步任务:AsyncTask或...
3. 避免持有不必要的Context引用:在Android开发中,Context是一个非常重要的类,但不当的使用会导致内存泄露。尤其是避免在静态变量中持有Activity的引用,因为静态变量生命周期与应用进程一致,Activity如果被销毁...
Android内存泄漏是开发过程中常见的问题之一,不仅会影响应用程序的性能,严重时还会导致应用崩溃。通过理解内存泄漏的概念、了解Java内存管理机制以及掌握一些常用的内存泄漏检测工具和方法,开发者可以有效地预防...
"mac_mat android内存泄漏分析工具"就是这样一个针对Android平台的工具,特别适合在Mac环境下对应用进行内存泄漏检测。 MAT(Memory Analyzer Tool)是由Eclipse基金会开发的一个强大的Java内存分析工具。尽管主要...
### Android内存泄漏调试经验分享 #### 一、概述 在Android开发中,内存泄漏是一个常见且需要重点关注的问题。由于Android设备通常配置有限,尤其是内存资源较为紧张,因此开发者需要格外注意避免内存泄漏的发生,...
Android内存泄漏是开发者必须关注的重要问题,因为它直接影响到应用的性能和用户体验。内存泄漏指的是本应被释放的对象由于某种原因仍然被持有,导致垃圾收集器(GC)无法回收这些资源,从而占用宝贵的内存空间。本文...
本文将深入探讨Android内存泄漏的概念、常见场景、预防措施以及检测方法。 首先,Android虚拟机的垃圾回收(GC)采用的是根搜索算法。这个算法从GC Roots(包括全局静态变量、活动线程、JNI引用等)开始遍历堆中的...
【Android内存泄露实践分析】 内存泄露在Android应用开发中是一个重要的问题,因为它直接影响到应用程序的性能、用户体验,甚至可能导致应用程序的崩溃。本文将深入探讨内存泄露的定义、影响、常见类型,以及解决...
2. 单例模式:单例对象的生命周期很长,若其内部持有Context引用,也会造成内存泄露。 3.匿名内部类:匿名内部类隐式持有了外部类的引用,如果外部类是Activity,可能导致Activity无法被正确回收。 4. Handler/...
### Android内存泄漏详解 #### 一、资源对象未关闭导致的内存泄漏 在Android开发过程中,内存泄漏是一个常见的问题,特别是在资源对象管理方面。资源对象如`Cursor`、文件流等,通常会在内部使用缓冲机制来提高...
本文将深入探讨Android内存泄露的概念、原因、检测方法以及如何进行有效修复。 首先,我们要理解什么是内存泄露。内存泄露是指程序在申请内存后,无法释放已不再使用的内存空间。在Android系统中,由于Java的自动...
`static`关键字用于声明类级别的变量,这些变量生命周期长,如果用来引用资源消耗大的实例,如Context,可能导致内存泄露。例如,一个静态的Drawable变量可能隐式地保持了对Context的引用,即使相关Activity已销毁...
1. **避免长时间持有Context引用**:Activity和Application都是Context的实例,但它们的作用不同。长时间持有Activity的引用,如在静态变量中存储,会导致Activity无法正常销毁,进而引发内存泄漏。例如,将Context...
然而,单例模式的一个主要问题是,如果单例对象持有了如Activity或Service等上下文(Context)对象的引用,就可能导致内存泄露。单例的生命周期通常与应用程序的生命周期相同,因此只要单例存在,它所引用的Context...
常见的Android内存泄露类型包括: 1. **静态变量引用**:当一个静态变量引用了一个Activity或Context,这个对象就无法被GC回收,因为静态变量在整个应用生命周期内都存在。解决方案是避免使用静态变量持有Activity...