一、内存泄露

内存泄漏:长生命周期的对象引用了短声明周期的对象,导致短生命周期的对象的工作在执行完后,无法在GC时被正常回收。

如何避免内存泄漏:

列举几个内存泄漏常见场景。

内部类引用导致Activity的泄漏。

内部类的优势是可以访问外部类,但内部类持有外部类实例的强引用往往导致内存泄漏。

Activity Context被传递到其他实例中。

这可能导致自身被引用而发生泄漏。所以要使用Application的Context。

临时Bitmap对象的及时回收。

注意临时Bitmap对象的及时回收(recycle掉),从而减轻GC的负担。

注意WebView的泄漏。

WebView的内部有一个类叫BrowserFrame,是Handler的子类,WebViewCoreThread通过它与Activity交互。如果Activity退出前,WebViewCoreThread处理了一个延时消息,就会造成内存泄漏。

注意Cursor、File是否及时关闭。

二、内存溢出

虚拟机为每个应用分配的内存是有限的,如果使用超过了这个限度就会发生内存溢出(OOM)。常见避免内存溢出的措施有:

使用更加轻量的数据结构。

比如SparseArray ArrayMap替代HashMap。
SparseArray通过两个数组,一个存储key(int型),另外一个存储value。二分查找法存储和读取数据。put数据的时候,按照key从小到大的顺序排列好。
ArrayMap原理跟SparseArray相似,它的数组mHash存储的是hash值,另一个数组mArray存mHash对应未知的key和value。HashMap在扩容时重新创建了对象,而ArrayMap对数组进行了复制。另外ArrayMap提供了数组收缩的功能,在clear或remove后,会重新收缩数组,释放空间。

Bitmap和ImageLoader框架

Bitmap是安卓中的图片,因为占用空间大,如果处理不好大图片或者大量图片,很容易造成OOM。
使用合适大小的图片,使用合适编码的Bitmap。
在加载时进行多级缓存。例如:Universal-Image-Loader框架。

避免内存泄露

内存泄漏会导致内存很多空间被浪费。

其他

  • 当界面不可见时释放内存、当内存紧张时释放内存
  • 避免在很小的ImageView上显示一张高分辨率的图片
  • 避免在Android里面使用Enum
  • 免在onDraw方法里面执行对象的创建:迅速增加内存的使用,而且很容易引起频繁的gc
  • 复用系统自带的资源
  • 注意在ListView ConvertView的复用
  • StringBuilder StringBuilder来替代频繁的“+
  • 谨慎使用large heap
  • 资源文件需要选择合适的文件夹进行存放
  • Try catch某些大内存分配的操作。在可能发生OOM的地方进行异常处理。

Universal-Image-Loader

【Android】の基础——内存溢出&内存泄漏&UIL

工作流程:

①UI:请求数据,使用唯一的Key值索引Memory Cache中的Bitmap。
② 内存缓存:缓存搜索,如果能找到Key值对应的Bitmap,则返回数据。否则执行第三步。
③ 硬盘存储:使用唯一Key值对应的文件名,检索SDCard上的文件。
④ 如果有对应文件,使用BitmapFactory.decode*方法,解码Bitmap并返回数据,同时将数据写入缓存。如果没有对应文件,执行第五步。
⑤ 下载图片:启动异步线程,从数据源下载数据(Web)。
⑥ 若下载成功,将数据同时写入硬盘和缓存,并将Bitmap显示在UI中。

内存缓存LruMemoryCache:

LruMemoryCache使用LinkedHashMap来缓存数据。当LinkedHashMap的accessOrder==true时,每一次get或put操作都会将所操作项移动到链表的尾部(链表头被认为是最少使用的,链表尾被认为是最常使用的。),当内存不够时优先提出链表头部的数据。

磁盘缓存UnlimitedDiscCache:

它的fileNameGenerator通过对象的哈希值来命名,避免重复。

性能分析工具

LeakCanary
LeakCanary是一个开源类库,用以检测内存泄漏。
TraceView
TraceView可以让我们查看方法执行的时间。

三、内存抖动

内存抖动是由于短时间内有大量对象进出Young Generiation区导致的,它伴随着频繁的GC。

避免内存抖动

  • 尽量避免在循环体内创建对象,应该把对象创建移到循环体外。
  • 注意自定义View的onDraw()方法会被频繁调用,所以在这里面不应该频繁的创建对象。
  • 当需要大量使用Bitmap的时候,试着把它们缓存在数组中实现复用。
  • 对于能够复用的对象,同理可以使用对象池将它们缓存起来。

相关文章:

  • 2022-12-23
猜你喜欢
  • 2022-02-28
  • 2021-09-12
  • 2022-12-23
  • 2021-11-29
  • 2021-12-20
  • 2021-06-11
  • 2021-09-05
相关资源
相似解决方案