`
ericbaner
  • 浏览: 177586 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Android内存泄露之Context引用

 
阅读更多

以下是对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 内存泄露的解决方法

    Android webview 内存泄露的解决方法 最近在activity嵌套webview显示大量图文发现APP内存一直在涨,没法释放内存,查了很多资料,大概是webview的一个BUG,引用了activity导致内存泄漏,所以就尝试传递...

    Android处理内存泄漏的代码例子

    本示例代码着重展示了如何避免Android应用中的内存泄漏,主要包括五个关键方面:关闭游标、重用适配器、回收图像、注销监听器以及释放引用。下面将详细解释这些方法。 1. 关闭游标: 在Android数据库操作中,游标是...

    使用Android Studio检测内存泄露(LeakCanary)

    内存泄露在Android开发中是一个非常重要的问题,因为它可能导致应用程序运行缓慢、消耗过多资源甚至崩溃。Android Studio提供了多种工具帮助开发者检测和解决内存泄露,其中包括Memory Profiler和LeakCanary。 ...

    android内存泄露的检测和排查

    本文将深入探讨Android内存泄漏的检测和排查方法,并通过一个锁屏内存泄漏的例子进行具体分析。 首先,我们需要理解什么是内存泄漏。在计算机科学中,内存泄漏是指程序在申请内存后,无法释放已不再使用的内存空间...

    避免 Android中Context引起的内存泄露

    在Android开发中,Context...总之,理解Context的作用和生命周期,以及在不同场景下如何正确使用,是避免Android内存泄露的关键。同时,保持良好的编程习惯,及时释放不再使用的资源,可以显著提升应用的性能和稳定性。

    AndroidApp定位和规避内存泄露方法研究

    2. 单例模式:单例中持有Context引用,若不妥善处理,可能导致内存泄露。 3. 内存泄漏的监听器:如注册了BroadcastReceiver、ContentObserver等,若忘记在合适时机注销,将导致内存泄露。 4. 异步任务:AsyncTask或...

    Android App定位和规避内存泄露方法研究

    3. 避免持有不必要的Context引用:在Android开发中,Context是一个非常重要的类,但不当的使用会导致内存泄露。尤其是避免在静态变量中持有Activity的引用,因为静态变量生命周期与应用进程一致,Activity如果被销毁...

    Android内存泄漏详解专栏

    Android内存泄漏是开发过程中常见的问题之一,不仅会影响应用程序的性能,严重时还会导致应用崩溃。通过理解内存泄漏的概念、了解Java内存管理机制以及掌握一些常用的内存泄漏检测工具和方法,开发者可以有效地预防...

    mac_mat android内存泄漏分析工具

    "mac_mat android内存泄漏分析工具"就是这样一个针对Android平台的工具,特别适合在Mac环境下对应用进行内存泄漏检测。 MAT(Memory Analyzer Tool)是由Eclipse基金会开发的一个强大的Java内存分析工具。尽管主要...

    Android 内存泄漏调试经验分享

    ### Android内存泄漏调试经验分享 #### 一、概述 在Android开发中,内存泄漏是一个常见且需要重点关注的问题。由于Android设备通常配置有限,尤其是内存资源较为紧张,因此开发者需要格外注意避免内存泄漏的发生,...

    Android内存泄漏总结1

    Android内存泄漏是开发者必须关注的重要问题,因为它直接影响到应用的性能和用户体验。内存泄漏指的是本应被释放的对象由于某种原因仍然被持有,导致垃圾收集器(GC)无法回收这些资源,从而占用宝贵的内存空间。本文...

    Android 内存泄露

    本文将深入探讨Android内存泄漏的概念、常见场景、预防措施以及检测方法。 首先,Android虚拟机的垃圾回收(GC)采用的是根搜索算法。这个算法从GC Roots(包括全局静态变量、活动线程、JNI引用等)开始遍历堆中的...

    Android 内存 泄露 实践分析1

    【Android内存泄露实践分析】 内存泄露在Android应用开发中是一个重要的问题,因为它直接影响到应用程序的性能、用户体验,甚至可能导致应用程序的崩溃。本文将深入探讨内存泄露的定义、影响、常见类型,以及解决...

    Android内存优化——常见内存泄露及优化方案

    2. 单例模式:单例对象的生命周期很长,若其内部持有Context引用,也会造成内存泄露。 3.匿名内部类:匿名内部类隐式持有了外部类的引用,如果外部类是Activity,可能导致Activity无法被正确回收。 4. Handler/...

    android 内存泄漏 摘抄

    ### Android内存泄漏详解 #### 一、资源对象未关闭导致的内存泄漏 在Android开发过程中,内存泄漏是一个常见的问题,特别是在资源对象管理方面。资源对象如`Cursor`、文件流等,通常会在内部使用缓冲机制来提高...

    android内存泄露

    本文将深入探讨Android内存泄露的概念、原因、检测方法以及如何进行有效修复。 首先,我们要理解什么是内存泄露。内存泄露是指程序在申请内存后,无法释放已不再使用的内存空间。在Android系统中,由于Java的自动...

    android内存分析

    `static`关键字用于声明类级别的变量,这些变量生命周期长,如果用来引用资源消耗大的实例,如Context,可能导致内存泄露。例如,一个静态的Drawable变量可能隐式地保持了对Context的引用,即使相关Activity已销毁...

    Android应用程序如何避免内存泄漏

    1. **避免长时间持有Context引用**:Activity和Application都是Context的实例,但它们的作用不同。长时间持有Activity的引用,如在静态变量中存储,会导致Activity无法正常销毁,进而引发内存泄漏。例如,将Context...

    Android内存优化——常见内存泄露及优化方案.pdf

    然而,单例模式的一个主要问题是,如果单例对象持有了如Activity或Service等上下文(Context)对象的引用,就可能导致内存泄露。单例的生命周期通常与应用程序的生命周期相同,因此只要单例存在,它所引用的Context...

    Android内存优化——常见内存泄露及优化方案.zip

    常见的Android内存泄露类型包括: 1. **静态变量引用**:当一个静态变量引用了一个Activity或Context,这个对象就无法被GC回收,因为静态变量在整个应用生命周期内都存在。解决方案是避免使用静态变量持有Activity...

Global site tag (gtag.js) - Google Analytics