android内存泄漏几点建议

来源:互联网 发布:树洞表白墙源码 编辑:程序博客网 时间:2024/06/01 16:48

android内存泄漏:
1.集合不再使用没有释放
2.单例模式的context
3.匿名内部类/非静态内部类

匿名内部类泄漏
public class MainActivity extends Activity {

Runnable ref1 = new MyRunable();
Runnable ref2 = new Runnable() {
@Override
public void run() {
}
};

}
ref1和ref2的区别是,ref2使用了匿名内部类。我们来看看运行时这两个引用的内存:
可以看到,ref1没什么特别的。
但ref2这个匿名类的实现对象里面多了一个引用:
this$0这个引用指向MainActivity.this,也就是说当前的MainActivity实例会被ref2持有,如果将这个引用再传入一个异步线程,此线程和此Acitivity生命周期不一致的时候,就造成了Activity的泄露。
解决:可以在onDestory()将ref2=null;

非静态内部类泄漏
public class MainActivity extends AppCompatActivity {
private static TestResource mResource = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(mManager == null){
mManager = new TestResource();
}
//…
}
class TestResource {
//…
} }
这样就在Activity内部创建了一个非静态内部类的单例,每次启动Activity时都会使用该单例的数据,这样虽然避免了资源的重复创建,不过这种写法却会造成内存泄漏,因为非静态内部类默认会持有外部类的引用,而该非静态内部类又创建了一个静态的实例,该实例的生命周期和应用的一样长,这就导致了该静态实例一直会持有该Activity的引用,导致Activity的内存资源不能正常回收。正确的做法为:
将该内部类设为静态内部类或将该内部类抽取出来封装成一个单例,如果需要使用Context,请按照上面推荐的使用Application 的 Context

4.Handler 造成的内存泄漏
解决方式:a.使用静态内部类 + WeakReference 这种方式 b.在onDestory 里面使用Handler.removeCallbacksAndMessages(null); 去除在messageQueue里面的handle和message
5.资源未关闭造成的内存泄漏
对于使用了BraodcastReceiver,ContentObserver,File,游标 Cursor,Stream,Bitmap等资源的使用,应该在Activity销毁时及时关闭或者注销,否则这些资源将不会被回收,造成内存泄漏。
比如:
◦ Bitmap 没调用 recycle()方法,对于 Bitmap 对象在不使用时,我们应该先调用 recycle() 释放内存,然后才它设置为 null. 因为加载 Bitmap 对象的内存空间,一部分是 java 的,一部分 C 的(因为 Bitmap 分配的底层是通过 JNI 调用的 )。 而这个 recyle() 就是针对 C 部分的内存释放。
◦ 构造 Adapter 时,没有使用缓存的 convertView ,每次都在创建新的 converView。这里推荐使用 ViewHolder。

0 0