Android中的内存泄漏是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。下面归纳下app开发中常见的内存泄漏。
1.尽量避免使用static变量
因为在Android中,static声明的变量的生命周期跟app是一样的,比如app切换到后台后 ,这时候内存占用率大的activity会优先被回收。而这时候这个activity的static变量也会被回收。所以这部分变量一定要小心。Android是进程不安全的,某些app被回收后也可能会重启,但是重启的时候这些static修饰 的变量也将再次初始化。
2. 静态内部类持有外部类的引用
在Java中内部类的定义与使用一般为成员内部类与匿名内部类,他们的对象都会隐式持有外部类对象的引用,影响外部类对象的回收。
GC只会回收没有被引用或者根集不可到达的对象(取决于GC算法),内部类在生命周期内始终持有外部类的对象的引用,造成外部类的对象始终不满足GC的回收条件,反映在内存上就是内存泄露。(如,Android中Activity的内存泄露)
最典型的例子就是Hanlder,一般我们在activity中这样定义一个Handler
Handler handler = new Handler() {
public void handleMessage(Message msg) {
//do something
};
};
handler.sendEmptyMessageDelayed(0, 100 * 1000);
1000像上面的代码片段,就会存在内存泄露的风险,因为handler占着Acitvity的引用阻止了系统进行GC回收操作。
更好的做法是将handler声明为静态变量,然后引用activity的
引用变量。
private static class MyHandler extends Handler {
WeakReference<MainActivity> mWeakReferenceActivity;
public MyHandler(MainActivity activity) {
mWeakReferenceActivity = new WeakReference<MainActivity>(activity);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (null != mWeakReferenceActivity) {
MainActivity _activity = mWeakReferenceActivity.get();
//_activity.dosomething();
}
}
}
3.Bitmap引起的内存泄漏
}Bitmap加载大图时候是很容易引起内存问题的。bitmap 在android2.3以下bitmap是存储在native内存区和java堆区的。当我们使用完图片后,java堆区域的内存可以被javaGC回收。但是native区由于是c++完成的操作,所以java不能进行回收。这时候如果越来越的图片也会造成内存泄漏。那怎么办呢?在android里面,我们应该使用recyecle去回收bitmap对象。recycle方法内部采用c++层方法去回收内存。
还有一点,就是我们加载图片的时候应该使用inSampleSize属性。这个属性可以帮助我们来缩放图片,从而节省内存。
属性。这个属性可以帮助我们来缩放图片,从而节省内存。
4.单例对象引起的内存泄漏
public class AppManager {
private static AppManager instance;
private Context context;
private AppManager(Context context) {
this.context = context ;// 使用传入的context,有可能是activity
}
public static AppManager getInstance(Context context) {
if (instance != null) {
instance = new AppManager(context);
}
return instance;
}
}
单例的静态特性导致其生命周期同应用一样长。
有时创建单例时如果我们需要Context对象,如果传入的是Application的Context那么不会有问题。如果传入的是Activity的Context对象,那么当Activity生命周期结束时,该Activity的引用依然被单例持有,所以不会被回收,而单例的生命周期又是跟应用一样长,所这就造成了内存泄露。
应该改成
public class AppManager {
private static AppManager instance;
private Context context;
private AppManager(Context context) {
this.context = context.getApplicationContext();// 使用Application 的context,避免由于单例对象引起内存泄漏
}
public static AppManager getInstance(Context context) {
if (instance != null) {
instance = new AppManager(context);
}
return instance;
}
}