Android applications are, at least on the T-Mobile G1, limited to 16 MB of heap. It's both a lot of memory for a phone and yet very little for what some developers want to achieve. Even if you do not plan on using all of this memory, you should use as little as possible to let other applications run without getting them killed. The more applications Android can keep in memory, the faster it will be for the user to switch between his apps. As part of my job, I ran into memory leaks issues in Android applications and they are most of the time due to the same mistake: keeping a long-lived reference to a Context.

On Android, a Context is used for many operations but mostly to load and access resources. This is why all the widgets receive aContext parameter in their constructor. In a regular Android application, you usually have two kinds of ContextActivity andApplication. It's usually the first one that the developer passes to classes and methods that need a Context:

@Override
protected void onCreate(Bundle state) {
super.onCreate(state); TextView label = new TextView(this);
label.setText("Leaks are bad"); setContentView(label);
}

This means that views have a reference to the entire activity and therefore to anything your activity is holding onto; usually the entire View hierarchy and all its resources. Therefore, if you leak the Context ("leak" meaning you keep a reference to it thus preventing the GC from collecting it), you leak a lot of memory. Leaking an entire activity can be really easy if you're not careful.

When the screen orientation changes the system will, by default, destroy the current activity and create a new one while preserving its state. In doing so, Android will reload the application's UI from the resources. Now imagine you wrote an application with a large bitmap that you don't want to load on every rotation. The easiest way to keep it around and not having to reload it on every rotation is to keep in a static field:

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);
}

This code is very fast and also very wrong; it leaks the first activity created upon the first screen orientation change. When aDrawable is attached to a view, the view is set as a callback on the drawable. In the code snippet above, this means the drawable has a reference to the TextView which itself has a reference to the activity (the Context) which in turns has references to pretty much anything (depending on your code.)

This example is one of the simplest cases of leaking the Context and you can see how we worked around it in the Home screen's source code (look for the unbindDrawables() method) by setting the stored drawables' callbacks to null when the activity is destroyed. Interestingly enough, there are cases where you can create a chain of leaked contexts, and they are bad. They make you run out of memory rather quickly.

There are two easy ways to avoid context-related memory leaks. The most obvious one is to avoid escaping the context outside of its own scope. The example above showed the case of a static reference but inner classes and their implicit reference to the outer class can be equally dangerous. The second solution is to use the Application context. This context will live as long as your application is alive and does not depend on the activities life cycle. If you plan on keeping long-lived objects that need a context, remember the application object. You can obtain it easily by calling Context.getApplicationContext() or Activity.getApplication().

In summary, to avoid context-related memory leaks, remember the following:

  • Do not keep long-lived references to a context-activity (a reference to an activity should have the same life cycle as the activity itself)
  • Try using the context-application instead of a context-activity
  • Avoid non-static inner classes in an activity if you don't control their life cycle, use a static inner class and make a weak reference to the activity inside. The solution to this issue is to use a static inner class with a WeakReference to the outer class, as done in ViewRoot and its W inner class for instance
  • A garbage collector is not an insurance against memory leaks

Avoiding memory leaks的更多相关文章

  1. Avoiding memory leaks in POSIX thread programming, 多线程避免内存泄漏

    默认创建的线程为joinable的,必须调用pthread_join()才可以释放所占的内存 创建分离线程detach, attr 线程函数运行结束,调用pthread_exit 其它线程调用pthr ...

  2. On Memory Leaks in Java and in Android.

    from:http://chaosinmotion.com/blog/?p=696 Just because it's a garbage collected language doesn't mea ...

  3. [转]Activitys, Threads, & Memory Leaks

    转自:http://www.androiddesignpatterns.com/2013/04/activitys-threads-memory-leaks.html http://www.cnblo ...

  4. Identify Memory Leaks in Visual CPP Applications —— VLD内存泄漏检测工具

    原文地址:http://www.codeproject.com/Articles/1045847/Identify-Memory-Leaks-in-Visual-CPP-Applications 基于 ...

  5. 解决:Detected memory leaks

    最近在一个项目中,程序退出后都出现内存泄漏: Detected memory leaks!Dumping objects ->{171} normal block at 0x05785AD0, ...

  6. [Angular2 Router] Exiting an Angular 2 Route - How To Prevent Memory Leaks

    In this tutorial we are going to learn how we can accidentally creating memory leaks in our applicat ...

  7. The Introduction of Java Memory Leaks

    One of the most significant advantages of Java is its memory management. You simply create objects a ...

  8. 【转】简单内存泄漏检测方法 解决 Detected memory leaks! 问题

    我的环境是: XP SP2 . VS2003 最近在一个项目中,程序退出后都出现内存泄漏: Detected memory leaks! Dumping objects -> {98500} n ...

  9. _CrtSetBreakAlloc简单内存泄漏检测方法,解决Detected memory leaks!问题

    我的环境是: XP SP2 . VS2003 最近在一个项目中,程序退出后都出现内存泄漏: Detected memory leaks! Dumping objects -> {98500} n ...

随机推荐

  1. exports和moudle. exports

    http://zihua.li/2012/03/use-module-exports-or-exports-in-node/ https://github.com/seajs/seajs/issues ...

  2. POJ3246-Balanced Lineup,好经典的题,做法和HDU-I hate it 一样~~

    Balanced Lineup Time Limit: 5000MS   Memory Limit: 65536K   Case Time Limit: 2000MS Description For ...

  3. 什么是Kubernetes?

    刚刚进学校实验室,第一次开会导师和小组同学说了n次Kubernetes,从来没听过,一脸懵逼. Kubernetes也有很多人把它叫K8S, 原文链接:http://omerio.com/2015/1 ...

  4. poj 2081 简单递推

    #include<stdio.h> #include<string.h> #define N 510000 int dp[N]; int f[10000000]; int ma ...

  5. bzoj 2721[Violet 5]樱花 数论

    [Violet 5]樱花 Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 671  Solved: 395[Submit][Status][Discuss ...

  6. [转]maven编译时出现读取XXX时出错invalid LOC header (bad signature)

    maven编译时出现读取XXX时出错invalid LOC header (bad signature) 一.发现问题右击pom.xml,run as —> maven install,会看到c ...

  7. 安卓巴士Android开发神贴整理

    10个经典的Android开源应用项目 http://www.apkbus.com/android-13519-1-1.html 安卓巴士总结了近百个Android优秀开源项目,覆盖Android开发 ...

  8. Python()- 面向对象三大特性----封装

    封装: [封装]         隐藏对象的属性和实现细节,仅对外提供公共访问方式.[好处] 1. 将变化隔离: 2. 便于使用:3. 提高复用性: 4. 提高安全性:[封装原则]      1. 将 ...

  9. python学习之-- 面向对象

    面向对象(简写:OOP) 面向对象编程定义:利用类和对象来创建各种模型,来实现对真实世界的描述. 优点:使程序更容易理解和维护以及扩展代码. 类定义:用来描述具有相同的属性和方法的对象的集合.(简单讲 ...

  10. 毕业bg--hdu1881(01背包)

    http://acm.hdu.edu.cn/showproblem.php?pid=1881 01 背包  先按发起人离开的时间从小到大排序 然后再套01背包的模板 #include <iost ...