---
内存优化
---

#### 目录

1. 设备分级
2. Bitmap 优化
3. 内存泄露

#### 前言

内存优化，应该从哪里着手呢？通常会从设备分级、Bitmap 优化和内存泄露这三个方面入手。

#### 设备分级

内存优化首先需要根据设备环境来综合考虑。

- 设备分级

  对于低端机用户可以关闭复杂的动画、或者某些功能；使用 565 格式的图片，使用更小的缓存内存等。在现实生活中，不是每个用户的设备都跟我们的测试机一样高端，在开发过程中我们要学会思考功能要不要对低端机开启、在资源紧张的时候能不能做降级。

- 缓存管理

  需要有一套统一的缓存管理机制，可以适当的使用内存；可以使用 onTrimMemory 回调，根据不同的状态决定释放多少内存。对于大项目来说，可能存在几十上百个模块，统一缓存管理可以更好的监控每个模块的缓存大小。

- 进程模型

  一个空进程也会占用 10M 的内存，减少应用启动的进程数，减少常驻进程、有节操的包活，对低端机内存优化非常重要。

- 安装包大小

  安装包中的代码、资源、图片以及 so 库的体积，跟它们占用的内存有很大的关系。一个 80M 的应用很难在 512 MB 的内存手机上流畅的运行。这种情况我们需要考虑针对低端机用户推出 4MB 的轻量版本，例如 Facebook Lite、今日头条极速版都是这个思路。


#### Bitmap 优化

Bitmap 内存一般占应用总内存很大一部分，所以内存优化永远无法避开图片内存这个永恒主题。

即使把所有的 Bitmap 都放到 Native 内存，并不代码图片内存问题就完全解决了，这样做只是提示了系统内存利用率，减少了 GC 带来的一些问题而已。

如果优化图片内存呢？这里介绍两种方法。

##### 方法一，统一图片库

图片内存优化的前提是收拢图片的调用，这样我们可以做整体的控制策略。例如低端机使用 565 格式、更加严格的缩放算法，可以使用 Glide、Fresco 或者采取自研都可以。而且需要进一步将所有 Bitmap.createBitmap、BitmapFactory 相关的接口也一并收拢。

##### 方法二：统一监控

在统一图片库后就非常容易监控 Bitmap 的使用情况了，这里有三点需要注意：

- 大图片监控

  我们需要注意某张图片内存占用是否过大，例如长宽远远大于 View 甚至屏幕的长宽。在开发过程中，如果检测到不合格的图片使用，应该立即弹出对话框提示图片所在的 Activity 和堆栈，让开发同学更快的发现并解决问题。在灰度和线上环境下可以将异常信息上报到后台，我们可以计算有多少比例的图片会超过屏幕的大小，也就是图片的“超宽率”。

- 重复图片监控

  重复图片指的是 Bitmap 的像素数据完全一致，但是有很多不同的对象存在。

- 图片总内存

  通过收拢图片使用，我们还可以统计应用所有图片占用的内存，这样在线上就可以按不同的系统、屏幕分辨率等维度去分析图片内存的占用情况。在 OOM 崩溃的时候，也可以把图片占用的总内存、Top N 图片的内存都写到崩溃日志中，帮助我们排查问题。

#### 内存泄露

内存泄露简单来说就是没有回收不再使用的内存，排查和解决内存泄露也是内存优化无法避开的工作之一。

内存泄露主要分两种情况，一种是同一个对象泄露，还有一种情况更加糟糕，就是每次都会泄露新的对象，可能会出现几百上千个无用的对象。

对于 Java 内存泄露，可以使用 LeakCanary 自动化检测方案。