美文网首页
Android 项目中对于内存优化的几个细节点

Android 项目中对于内存优化的几个细节点

作者: Merbng | 来源:发表于2019-03-14 22:41 被阅读0次

定义

当一个对象已经不需要再使用了,本应该被回收掉,而另一个正在使用的对象持有他的引用,导致对象不能被回收。因为不能被及时回收的本该被回收的内存,就产生了内存泄露。如果内存泄露太多会导致程序没有办法申请内存,最后出现内存溢出的错误。

场景和解决办法

Android开发中经常出现内存泄露的点,

  • 使用单例模式
  • 非静态内部类的静态实例
非静态内部类会持有外部类的引用,如果非静态内部类的实例是静态的,
就会长期维持着外部类的引用,组织被系统回收,解决办法就是使用静态内部类。
  • 多线程相关的匿名内部了和非静态内部类
匿名内部类同样会持有外部类的引用,如果在线程中执行耗时操作就有可能发生内存泄露
导致外部类无法回收,直到耗时任务结束,解决办法就是在页面退出时结束线程中的任务。
  • Handler内存泄漏
Handler导致的内存泄露也可以被归纳为非静态内部类导致的,
handler内部message是被存储在MessageQueue中的,
有些message不能马上被处理,存在的时间会很长,导致handler无法被回收,
如果handler是非静态的,就会导致他的外部类无法被回收,
解决办法就是
1.使用静态handler,外部类引用使用弱引用处理。
2.在退出页面时移除消息队列中的消息。
  • Context导致内存泄露
根据场景使用Activity的Context还是Application的Context,
因为二者的生命周期不同,对于不必须使用Activity的Context的场景(dialog),
一律采用Application的Context,单例模式是最常见的发生此泄露的场景,
比如传入一个Activity的Context被静态类引用,导致无法回收。
  • 静态View导致泄露
使用静态View可以避免每次启动Activity都去读取并渲染View,
但静态View会持有Activity的引用,导致无法回收,
解决办法就是
在Activity销毁的时候将静态View设置为null(View一旦被加载到界面中将会持有一个Context对象的引用)
  • WebView导致的内存泄露
WebView 只要使用一次,内存就不会被释放,所以WebView都存在内存泄露的问题,
通常解决办法是为WebView单开一个进程,使用AIDL就行通信,根据业务需求在合适的时机释放。
  • 使用静态变量
  • 资源未关闭导致
如Cursor,File等,内部往往都使用了缓存,会造成内存泄露,一定要确保关闭它并将引用置为null
  • 集合中的对象未清理
集合用于保存对象,如果集合越来越大,不进行合理的清理,尤其是入股集合是静态的
  • 监听器未关闭
很多需要register和unregister的系统服务要在合适的时候进行unregister,
手动添加的listener也需要及时移除。
  • 使用Asynctask
  • 使用Bitmap
bitmap是比较占内存的,所以一定要在不使用的时候及时进行清理,
避免静态变量持有大的bitmap对象

优化

  • 当查询完数据库之后,及时关闭Cursor对象。
  • 记得在ActivityonPause方法中调用unregisterReceiver()方法,反注册广播。
  • 避免Context内存泄露,比如在4.0.1之前的版本上不要将Drawer对象置为static。当一个Drawable绑定到了View上,实际上这个View对象就会成为这个Drawable的一个CallBack成员变量,静态的SBackground持有TextView对象lable的引用,而lable只有Activity的引用,而Activity会持有其他更多对象的引用,sBackground生命周期要长于Activity,当屏幕旋转时,Activity无法销毁,这样就产生了内存泄露的问题。
  • 尽量不要在Activity中使用非静态内部类,因为非静态内部类会隐式持有外部类实例的引用,当非静态内部类的引用的生命周期长于Activity的生命周期时,会导致Activity无法被GC正常回收掉。
  • 谨慎使用线程Thread,很多人会犯这样的错误:Java中的Thread有一个特点就是他们都是直接被GC Root所引用,也就是说Dalvik虚拟机对所有被激活状态的线程都是持有强引用 ,导致GC永远都无法回收掉这些线程对象,除非线程被手动停止并置为null或者用户直接kill掉进程操作,所以当使用线程时,一定要考虑在Activity退出时,及时将线程也停止并释放掉。
  • 使用Handler时,要么放在单独的类文件中, 要么就是使用静态内部类,因为静态的内部类不会持有外部类的引用,所以不会导致外部类实例的内存泄露

参考资料:
Android性能优化篇之内存优化--内存泄漏
资料

相关文章

网友评论

      本文标题:Android 项目中对于内存优化的几个细节点

      本文链接:https://www.haomeiwen.com/subject/gevhmqtx.html