`
410063005
  • 浏览: 181153 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

(翻译)avoiding memory leaks

 
阅读更多

原文来自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
  • 垃圾回收器并不是保证避免内存泄漏

 

分享到:
评论

相关推荐

    Android代码-Console

    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 ...

    C++ Game Development Cookbook-Packt Publishing

    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...

    Efficient MIDP Programming

    - **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. ...

    common-sense-c-advice-and-warnings-for-c-and-c-programmers.9781882419005.32087

    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 ...

    Expert C++ Programming-Packt Publishing(2018).epub

    ​ ​You’ll ​ ​get ​ ​tips ​ ​on ​ ​avoiding ​ ​memory ​ ​leaks using ​ ​smart-pointers. ​ Section 2, Mastering C++ Multithreading, ​you’ll ​ ​see ​ ​how ​ ​multi-threaded ...

    Springer.The.Developer’s.Guide.to.Debugging.2008.pdf

    4.3.3 Detecting Memory Leaks . . . . . . . 38 4.4 Example 2: Broken Calls to Memory Allocation/Deallocation . . 38 4.5 Combining Memory and Source Code Debuggers . . . . . . 40 4.6 Cutting Down the ...

    Chucks_VBA_Reference_rev17.docx

    Strategies for releasing memory in VBA to prevent memory leaks and ensure optimal performance. **Checking Condition (Page 18)** Tips for efficiently checking conditions in VBA code to make the logic...

Global site tag (gtag.js) - Google Analytics