Android内存分配回收机制
进程的优先级
Anroid基于进程中运行的组件及其状态规定了默认的五个回收优先级: 优先级从高到低是:
- Foreground process(前台进程)
- Visible process(可见进程)
- Service process(服务进程)
- Background process(后台进程)
- process(空进程)
系统根据优先级的高低进行回收,优先级越低,越容易被回收。 Android中由ActivityManagerService 集中管理所有进程的内存资源分配。 ActivityManagerService会对所有进程进行评分(存放在变量adj中),然后再讲这个评分更新到内核,由内核去完成真正的内存回收(lowmemorykiller, Oom_killer)
对内存进行优化可以从下面几点入手:
1. 解决内存泄漏
内存泄漏 使用Leakcanary,memory profiler,MAT监测内存泄漏问题,常见的内存泄漏见下面的总结
2. 收敛线程
线程是一种系统资源,本身创建就会带来内存开销(每创建一个线程至少需要64k内存),同时操作系统对单进程可创建的线程数也是有限制的。
所以代码中禁止使用new Thread的方式创建线程,而是通过线程池来统一创建管理线程。 可以参考asynctask创建一个核心线程数为2~4,最大线程数是cpucount * 2 + 1,使用有界的阻塞队列的线程池。
线程池使用不合理会导致oom问题,例如使用FixedThreadPool和SingleThreadPool时,由于这两个线程池的任务队列是无界的LinkedBlockingQueue,所以无限制的添加新任务,当任务过多时会导致OOM发生,或者使用CachedThreadPool时,最大线程数没有限制,创建过多线程,导致OOM
bitmap优化
bitmap压缩和缓存复用
3. 内存抖动
Android里内存抖动是指内存频繁的分配和回收,而频繁的GC会导致卡顿,严重时导致oom
- 比如string字符串拼接,最好使用StringBuilder
- 在自定义View的onDraw方法中不要创建局部变量
4. 瘦身
apk包体积减小,就会减少应用所需的系统内存。
5. 其他
- 常用数据结构优化,使用SparseArray或ArrayMap代替HashMap
- 布局优化,减少view的层级,使用merge和viewstub标签,使用约束布局
- 数据相关:序列化数据使用protobuf可以比xml省30%内存,慎用shareprefercnce,因为对于同一个sp,会将整个xml文件载入内存,有时候为了读一个配置,就会将几百k的数据读进内存,数据库字段尽量精简,只读取所需字段。使用微信mmkv代替shareprefercnce
- dex优化,代码优化,谨慎使用外部库, 有人觉得代码多少于内存没有关系,实际会有那么点关系,现在稍微大一点的项目动辄就是百万行代码以上,多dex也是常态,不仅占用rom空间,实际上运行的时候需要加载dex也是会占用内存的(几M),有时候为了使用一些库里的某个功能函数就引入了整个庞大的库,此时可以考虑抽取必要部分,开启proguard优化代码,使用Facebook redex使用优化dex(好像有不少坑)。