工具
查看已经分配的内存空间与目前空闲的内存空间,我们可以用Android Studio里面的Memory Monitor;
分析内存泄露,我们可以使用著名的MAT, 还可以使用更加智能的LeakCanary
原则
5R法则,他们分别是ReduceReuse(重用那些已经分配过的对象)Recycle(回收不再使用的对象,避免内存泄漏)Refactor(重构已有的内存使用方案)Revalue(重新评估使用内存的策略)
Reduce
差异化对待图片资源
假如我们以xxhdpi为基准,提供了针对这个dpi手机的引导页,这种情况很容易导致某个hdpi的手机因为没有提供这个level的图片,由系统来对高级别的图片来做scale处理,这很容易导致OOM,如果我们发现自己的app出现了不少的InflationException,那么就有必要注意看下是不是自己在XML里面引用了一张大图片。页面按需加载。
例如,我们知道ViewPager可以设置同时存在的Page数量,如果非必要,千万别扩大默认缓存的页面数量。与左右滑动类似的是,上下滑动的预加载处理,需要控制好预加载的数据量。减少Bitmap的内存占用
必须考虑的两点是:缩放比例与解码率- inSampleSize:缩放比例,在真实decode bitmap之前,我们需要事先拿到图片的大小,计算出一个相对比较合适的缩放比例,避免不必要的大图载入。
- decode format,选择ARGB_8888/RBG_565/ARGB_4444/ALPHA_8,存在很大差异。Try catch某些大内存分配的操作对于那些推测可能发生OOM的大图解码操作,可以适当考虑加入try catch机制,一旦catch到OOM异常,可以尝试把采样比例做降级处理之后,进行再次decode。
Reuse
- 使用Pools模型,使用pools可以避免heap空间的碎片化,减少gc的频率与时间。
- Bitmap的inBitmap复用。为了提高bitmap的使用效率,Android系统设计了inBitmap的高级属性,使用inBitmap属性可以告知Bitmap解码器去尝试使用已经存在的内存区域,新解码的bitmap会尝试去使用之前那张bitmap在heap中所占据的pixel data内存区域,而不是去问内存重新申请一块区域来存放bitmap。
- ListView/GridView中的ConvertView的复用。
- 避免频繁的创建与回收对象。类似onDraw,还有for循环等操作也需要特别注意在里面频繁创建对象的操作,例如需要注意避免在for循环里面频繁做字符串拼接的操作。解决这个问题可以考虑StringBuilder。
Recycle
主要就是回收不再使用的对象,避免内存泄漏。(详见内存泄露)
Recycle
- 使用优化过后的数据结构 。考虑使用ArrayMap/SparseArray而不是HashMap等传统数据结构,避免在Android里面使用Enum
- 减少内存的碎片化,优先分配尺寸更大的对象
3)优化布局,减少内存消耗。 扁平化布局:占用的内存就越少,效率越高。我们需要尽量保证布局足够扁平化,当使用系统提供的View无法实现足够扁平的时候考虑使用自定义View来达到目的。