`
tansitongba
  • 浏览: 484685 次
文章分类
社区版块
存档分类
最新评论

如何避免Android内存泄漏

 
阅读更多

至少在T-Mobile G1上Android应用在堆上分配的内存大小被限制16MB以内。对于手机来说,这是个不小的内存,但是这仍然远远不能满足一些开发者的需求。但是,即使你不打算使用所有的内存空间,你也应该尽可能地少用内存,从而使得其他应用能够运行而不是被杀掉。因为Android能够在内存中保持的应用越多,那么用户切换应用的速度就会越快。作为我工作的一部分,我在做android应用开发的时候也会陷入内存泄漏的问题中,大多数时候内存的泄漏都是由于犯了相同的错误:长期持有了一个Context的引用。

Android上 ,Context可以用于很多操作,但是大部分时候是用来加载以及使用资源。这就是为什么所有的widgets在他们的构造函数中接受一个Context参数。在一般的android应用中,你通常有两种Context:分别是Activity和Application。通常的,当我们的类和方法需要使用到context时,我们传递的是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所拥有的一切;通常的,这指的是完整的视图层级结构以及所有它的资源。因此,如果你泄露了一个Context(“ 泄漏 ”意味着你保持着它的一个引用,从而使它不能被垃圾回收机制回收),就意味着你泄漏了很多的内存。如果你不小心, 泄漏一 个activity的所有资源真的非常容易。

当 屏幕的方向发生改变的时候,系统默认将会销毁当前的activity并且创建一个新的activity同时保持着原有的状态。在做这个的时候,Android会从资源重新加载应用的UI。现在,想象一下你写了一个应用,这个应用有一张很大的bitmap。你不想再每一次旋转的时候重新加载它。最简单的方法让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,这个在第一次屏幕改变时被创建的activity。当一个Drawable被关联到一个view上,这个view就相当于在drawable上设置的一个回调。在上面的代码片段中,这表示drawable有一个TextView的引用,而这个TextView又拥有一个activity的引用(Context),activity依次引用了几乎所有的东西(取决于你的代码)。

这个例子展示了一个最简单的Context 泄漏的情况,你可以在Home screen 的源码中看到我们是如何解决这个问题的( 查找unbindDrawables() 方法) ,这就是当activity 被销毁的时候将drawables 的回调设为null 。有趣的是,你可能创造出一系列context泄漏的情况有很多,这非常糟糕。他们会是你很快内存溢出。

有两种简单的方法来避免context 相关的内存泄漏。最显著地一个是避免context 逃出他自己的范围之外。上面的例子就展示了使用静态引用的情况,而内部类和他们对外部类的的隐式引用也是同样危险的。第二种方法是使用Application context 。这个context 的生存周期和你的应用的生存周期一样长,而不是取决于activity 的生存周期。如果你想保持一个长期生存的对象,并且这个对象需要一个context ,记得使用application 对象。你可以通过调用Context.getApplicationContext() or Activity.getApplication() 来获得。

总而言之,想要避免context 相关的内存泄漏 ,记住以下几点:
· 不要对activity 的context 长期引用( 一个activity 的引用的生存周期应该和activity 的生命周期相同)
· 试着使用关于application的 context 来替代和activity相关的context
· 如果一个acitivity 的非静态内部类的生命周期不受控制,那么避免使用它;使用一个静态的内部类并且对其中的activity 使用一个弱引用。解决这个问题的方法是使用一个静态的内部类,并且对它的外部类有一WeakReference,就像在ViewRoot中内部类W所做的就是这么个例子。
· 垃圾回收器不能处理内存泄的保障。



分享到:
评论

相关推荐

    Android webview 内存泄露的解决方法

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

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

    Android处理内存泄漏的代码例子。用于演示避免内存泄漏的几种方法,包括:关闭游标、重用适配、回收图像、注销监听、释放引用。

    Android内存泄漏简介

    Android内存泄漏简介 不少人认为java程序,因为有垃圾回收机制,应该没有内存泄漏 1.引用没有释放造成的内存泄漏 2.资源对象没有关闭造成的内存泄漏 3.一些不良代码造成的内存压力 4.JNI代码的内存泄漏

    Android 内存泄露原因分析

    Android 内存泄露原因分析。通过原因分析,再接合代码可查明具体原因,发现对策

    Android 内存泄露 Mat工具分析

    Android 内存泄露 Mat工具分析。非常好的分析工具讲解

    Android避免内存泄露

    如何高效避免Android内存泄露,文档时根据我多年的Android经验编写而成,希望对您有所帮助。

    android内存泄露测试

    android 内存泄露测试.

    Android Native 内存泄漏系统化解决方案

    主要介绍了Android Native 内存泄漏系统化解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

    Android内存泄漏调试教程

    Android内存泄漏调试教程,Android内存泄漏调试教程,Android内存泄漏调试教程

    android内存泄露的检测和排查

    android内存泄露的检测和排查,已经附带一个锁屏内存泄露的例子分析。

    android检查内存泄露

    android检查内存泄露和用法 <!--==============================================================================--> android:name="com.squareup.leakcanary.internal.HeapAnalyzerService" android:enabled...

    Android内存OOM优化详解.pdf

    Android 内存 OOM 优化和治理,Android 内存泄漏原因详解与应对措施,Android 中的 Bitmap 使用详解,Android 中的 Bitmap 内存治理和优化详解,Android 内存分析命令详解,Java内存模型。Android 内存 OOM 优化和...

    android系统分析内存泄露测试

    android系统分析内存泄露测试android系统分析内存泄露测试android系统分析内存泄露测试

    android 内存泄露 分析方法

    android 内存泄露 分析方法.非常难对应的问题。首先弄明白原理

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

    本篇文章主要介绍了用Android Studio检测内存泄露的问题的解决方法,Android Studio在为我们提供了良好的编码体验的同时,也提供了许多对App性能分析的工具,下面我们一起来了解一下。

    androidStudio内存泄漏分析

    用AndroidStudio内存泄漏分析,亲测可用,在项目中充分验证。

    android内存泄露:4、Toast的错误使用导致内存泄露

    详细可参考博文:原创 android内存泄露:3、Handler的错误使用导致内存泄露 ,这篇文章我们将介绍:Toast的错误使用导致内存泄露 二、Toast的错误使用导致内存泄露 我们通常,连续点击按钮多次提示的 Toast,它...

    Android 内存泄漏

    自己收集的android方面关于内存泄漏方面的视频以及学习资料,自己之前花钱搞到的,现在对外公开。文档里面是链接和密码,永久有效!

    Android 内存泄漏调试经验分享

    二、Android(Java)中常见的容易引起内存泄漏的不良代码 1 (一) 查询数据库没有关闭游标 2 (二) 构造Adapter时,没有使用缓存的 convertView 3 (三) Bitmap对象不在使用时调用recycle()释放内存 4 (四) 释放对象的...

    android 内存泄漏 摘抄

    android 的内存泄漏 和anr的处理情况,挺不错的资源

Global site tag (gtag.js) - Google Analytics