【性能优化】Android内存优化总结和实践

1,995 阅读3分钟

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压缩和缓存复用

【性能优化】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(好像有不少坑)。

Android 内存优化总结&实践