首页 > 系统 > Android > 正文

Android 内存泄漏 总结

2019-11-09 15:44:00
字体:
来源:转载
供稿:网友

什么是内存泄漏?

Android 编程所使用的 java 是一门使用垃圾收集器(GC, garbage collection)来自动管理内存的语言,它使得我们不再需要手动调用代码来进行内存回收。那么它是如何判断的呢?简单说,如果一个对象,从它的根节点开始不可达的话,那么这个对象就是没有引用的了,是会被垃圾收集器回收的,其中,所谓的 “根节点” 往往是一个线程,比如主线程。因此,如果一个对象从它的根节点开始是可达的有引用的,但实际上它已经没有再使用了(或者说重要性已经很低),是无用的,这样的对象就是内存泄漏的对象;

例子: 1:非静态内部类和匿名内部类造成内存泄漏

PRivate Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); }};

如果此时handler 被传到网络线程,那界面结束后也不能被回收 原因: 网络线程持有 handler,handler 持有整个外部类Activity,导致真个界面的图片等不能被回收! 解决: 使用静态内部类加 WeakReference;

private StaticHandler mHandler = new StaticHandler(this);public static class StaticHandler extends Handler { private final WeakReference<Activity> mActivity; public StaticHandler(Activity activity) { mActivity = new WeakReference<Activity>(activity); } @Override public void handleMessage(Message msg) { super.handleMessage(msg); }}

2:静态变量持有不需要的对象

public class CommUtil { private static CommUtil instance; private Context context; private CommUtil(Context context){ this.context = context; } public static CommUtil getInstance(Context mcontext){ if(instance == null){ instance = new CommUtil(mcontext); } // else{ // instance.setContext(mcontext); // } return instance; }

当调用getInstance时,如果传入的context是Activity的context。只要这个单利没有被释放,那么这个 Activity也不会被释放一直到进程退出才会释放。

解决: 1:使用完后将不再需要的Context置空; 2:尽量使用Applicaticn Context 3:使用 WeakReference 持有 context ;

3:不需要用的监听未移除会发生内存泄露

//例子1:// tv.setOnClickListener();//监听执行完回收对象 //add监听,放到集合里面 tv.getViewTreeObserver().addOnWindowFocusChangeListener(new ViewTreeObserver.OnWindowFocusChangeListener() { @Override public void onWindowFocusChanged(boolean b) { //监听view的加载,view加载出来的时候,计算他的宽高等。 //计算完后,一定要移除这个监听 tv.getViewTreeObserver().removeOnWindowFocusChangeListener(this); } }); // 例子2: SensorManager sensorManager = getSystemService(SENSOR_SERVICE); Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ALL); sensorManager.registerListener(this,sensor,SensorManager.SENSOR_DELAY_FASTEST); //不需要用的时候记得移除监听 sensorManager.unregisterListener(listener);

解决:及时移除监听,网络加载监听一般框架会用WeakReference 持有

4.资源未关闭引起的内存泄露情况 比如:BroadCastReceiver、Cursor、Bitmap、IO流、自定义属性attributeattr.recycle()回收

解决:当不需要使用的时候,要记得及时释放资源。否则就会内存泄露。

5.无限循环动画 没有在onDestroy中停止动画,否则Activity就会变成泄露对象。 比如:轮播图效果。

内存泄漏检测: 1:Android Monitors的内存分析 最直观的看内存增长情况,对比动作操作前GC后内存跟动作操作后GC内存知道该动作是否发生内存泄露。 2:MAT 工具分析 3:Square 公司开源的 LeakCanary 方案 (使用待续…)


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表