Android 内存优化——常见内存泄露及优化方案
如果一个无用对象 (不需要再使用的对象)仍然被其他对象持有引用,造成该对象无法被系统回
收,以致该对象在堆中所占用的内存单元无法被释放而造成内存空间浪费,这中情况就是内存泄
露。
在Android 开发中,一些不好的编程习惯会导致我们的开发的app 存在内存泄露的情况。下面介
绍一些在Android 开发中常见的内存泄露场景及优化方案。
单例导致内存泄露
单例模式在Android 开发中会经常用到,但是如果使用不当就会导致内存泄露。因为单例的静态
特性使得它的生命周期同应用的生命周期一样长,如果一个对象已经没有用处了,但是单例还持
有它的引用,那么在整个应用程序的生命周期它都不能正常被回收,从而导致内存泄露。
public class AppSettings {
private static AppSettings sInstance;
private Context mContext;
private AppSettings(Context context) {
this.mContext = context;
}
public static AppSettings getInstance(Context context) {
if (sInstance == null) {
sInstance = new AppSettings(context);
}
return sInstance;
}
}
像上面代码中这样的单例,如果我们在调用getInstance(Context context)方法的时候传入的
context 参数是Activity、Service 等上下文,就会导致内存泄露。
以Activity 为例,当我们启动一个Activity,并调用getInstance(Context context)方法去获取
AppSettings 的单例,传入Activity .this 作为context,这样AppSettings 类的单例 sInstance 就
持有了Activity 的引用,当我们退出Activity 时,该Activity 就没有用了,但是因为 sIntance
作为静态单例 (在应用程序的整个生命周期中存在)会继续持有这个Activity 的引用,导致这个
Activity 对象无法被回收释放,这就造成了内存泄露。
为了避免这样单例导致内存泄露,我们可以将 context 参数改为全局的上下文:
private AppSettings(Context context) {
this.mContext = context.getApplicationContext();
}
全局的上下文Application Context 就是应用程序的上下文,和单例的生命周期一样长,这样就避
免了内存泄漏。
单例模式对应应用程序的生命周期,所以我们在构造单例的时候尽量避免使用Activity 的上下文,
而是使用Application 的上下文。
静态变量导致内存泄露
静态变量存储在方法区,它的生命周期从类加载开始,到整个进程结束。一旦静态变量初始化后,
它所持有的引用只有等到进程结束才会释放。
比如下面这样的情况,在Activity 中为了避免重复的创建info,将 sInfo 作为静态变量:
public class MainActivity extends AppCompatActivity {
private static Info sInfo;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (sInfo != null) {
sInfo = new Info(this);
}
}
}
class Info {
public Info(Activity activity) {
}
}
Info 作为Activity 的静态成员,并且持有Activity 的引用,但是 sInfo 作为静态变量,生命周期
肯定比Activity 长。所以当Activi