自研的内存分析利器开源了!Android Bitmap Monitor 助你定位不合理的图片使用

大家好,我是 shixin。

在日常工作中,咱们往往只重视 Java 内存运用情况,这首要是因为 Java 内存剖析相关的东西比较多。与之不同的是,图片内存剖析的东西比较少,当剖析图片内存问题时咱们需求花费很大的精力。

咱们知道,Android 运用运用的内存中,图片总是占有不少份额。拿小米 12 来说,3200 x 1440 的分辨率,一张全屏的图片至少要占用 17MB(3200 x 1440 x 4 )。假如缓存里多几张,基本就要达到上百 MB。加载的图片稍有不妥,就可能导致运用的内存溢出溃散大大增加。

因而,咱们需求这样的东西:能够快速发现运用内加载的图片是否合理,比方巨细是否适宜、是否存在走漏、缓存是否及时整理、是否加载了当时并不需求的图片等等。

AndroidBitmapMonitor 正是为此而生!它是一个开源的 Android 图片内存剖析东西,能够协助开发者快速发现运用的图片运用是否合理,支撑在线下和线上运用

AndroidBitmapMonitor 供给了这些功用:

  1. 获取内存中的 Bitmap 数量及占用内存
  2. 查看 Bitmap 创立库房及线程
  3. 导出 Bitmap 图片,协助直接定位问题所属事务
  4. 动态开关,能够在任意时刻开端和结束

功用介绍

  • 支撑 Android 4.4 – 13 (API level 19 – 33)
  • 支撑 armeabi-v7a 和 arm64-v8a
  • 支撑线下实时查看图片内存情况 和 线上数据计算

能够供给的功用:

  1. 获取内存中的图片数量及占用内存
  2. 获取 Bitmap 创立库房及线程
  3. 全版别 Bitmap Preview,在库房无法看出问题时,能够用来定位图片所属事务

动图:

自研的内存分析利器开源了!Android Bitmap Monitor 助你定位不合理的图片使用

中心功用截图:

自研的内存分析利器开源了!Android Bitmap Monitor 助你定位不合理的图片使用

悬浮窗中能够实时查看到图片内存

自研的内存分析利器开源了!Android Bitmap Monitor 助你定位不合理的图片使用

内存中的图片信息

自研的内存分析利器开源了!Android Bitmap Monitor 助你定位不合理的图片使用

某张图片的详细信息

运用文档

首要有四步:

  1. 增加 gradle 依靠
  2. 初始化配置
  3. 在需求的时候调用 start 和 stop
  4. 获取数据

1. 在 build.gradle 中增加依靠

Android Bitmap Monitor 发布在 mavenCentral 上,因而首先需求确保您的项目有运用 mavenCentral 作为库房。

您能够在根目录的 build.gradle 或者 setting.gradle 中增加以下代码:

allprojects {
    repositories {
        //...
        //增加 mavenCentral 依靠
        mavenCentral()
    }
}

接着在详细事务的 build.gradle 文件中增加依靠:

android {
    packagingOptions {
        pickFirst 'lib/*/libshadowhook.so'
    }
}
dependencies {
    implementation 'io.github.shixinzhang:android-bitmap-monitor:1.0.2'
}

请注意:为了防止和其他库冲突,上面的 packagingOptions 中 pickFirst 'lib/*/libshadowhook.so' 是必要的。

增加完依靠并履行 gradle sync 后,下一步就是在代码里进行初始化和发动。

2. 初始化

初始化需求调用的 API 是 BitmapMonitor.init

        long checkInterval = 10;
        long threshold = 100 * 1024;
        long restoreImageThreshold = 100 * 1024;;
        String dir = this.getExternalFilesDir("bitmap_monitor").getAbsolutePath();
        BitmapMonitor.Config config = new BitmapMonitor.Config.Builder()
                .checkRecycleInterval(checkInterval)    //查看图片是否被收回的间隔,单位:秒 (主张不要太频频,默认 5秒)
                .getStackThreshold(threshold)           //获取库房的阈值,当一张图片占有的内存超过这个数值后就会去抓栈
                .restoreImageThreshold(restoreImageThreshold)   //复原图片的阈值,当一张图占有的内存超过这个数值后,就会复原出一张原始图片
                .restoreImageDirectory(dir)             //保存复原后图片的目录
                .showFloatWindow(true)                  //是否展现悬浮窗,可实时查看内存巨细(主张只在 debug 环境翻开)
                .isDebug(true)
                .context(this)
                .build();
        BitmapMonitor.init(config);

当 showFloatWindow 为 true 时,初次发动 app 需求授予悬浮窗权限。

3. 敞开和中止监控

初始化完成后,能够在任意时刻调用 start/stop 敞开和中止监控:

        //敞开监控,方法1
        BitmapMonitor.start();
        //敞开方法2,供给页面获取接口,主张运用
        BitmapMonitor.start(new BitmapMonitor.CurrentSceneProvider() {
            @Override
            public String getCurrentScene() {
                //返回当时顶部页面称号
                if (sCurrentActivity != null) {
                    return sCurrentActivity.getClass().getSimpleName();
                }
                return null;
            }
        });
        //中止监控
        BitmapMonitor.stop();

上面的代码中,敞开方法 2 的参数用来获取图片创立时的页面称号,这个接口能够协助知道大图是在哪个页面创立的。假如不想供给这个接口能够运用敞开方法 1。

那咱们该在什么运用敞开监控呢?

一般有「大局敞开」和「分事务敞开」两种运用方法:

  1. 大局敞开:一发动就 start,用于了解整个 APP 运用进程中的图片内存数据
  2. 分事务敞开:在进入某个事务前 start,退出后 stop,用于了解特定事务的图片内存数据

4. 获取数据

在初始化完成并敞开监控后,咱们就能够拦截到每张图片的创立进程。

Android Bitmap Monitor 供给了两种获取内存中图片数据的 API:

  1. 守时回调 addListener
  2. 主动获取数据 dumpBitmapInfo

守时回调 是指注册一个 listener,这个接口的回调会依照一守时刻间隔被调用,能够用来做实时监控

        BitmapMonitor.addListener(new BitmapMonitor.BitmapInfoListener() {
            @Override
            public void onBitmapInfoChanged(final BitmapMonitorData data) {
                Log.d("bitmapmonitor", "onBitmapInfoChanged: " + data);
            }
        });

间隔时刻是初始化时传递的参数 checkRecycleInterval,返回的数据结构如下所示:

public class BitmapMonitorData {
    //前史创立的总图片数
    public long createBitmapCount;
    //前史创立的总图片内存巨细,单位 byte
    public long createBitmapMemorySize;
    //当时内存中还未收回的图片数
    public long remainBitmapCount;
    //当时内存中还未收回的图片内存巨细,单位 byte
    public long remainBitmapMemorySize;
    //走漏(未开释)的 bitmap 数据
    public BitmapRecord[] remainBitmapRecords;
    //...
}

主动获取数据 是指主动调用 BitmapMonitor.dumpBitmapInfo() 获取内存中的一切数据,能够用在内存升高时上报数据

        //获取一切数据
        BitmapMonitorData bitmapAllData = BitmapMonitor.dumpBitmapInfo();
        Log.d("bitmapmonitor", "bitmapAllData: " + bitmapAllData);
        //仅获取数量和内存巨细,不获取详细图片信息
        BitmapMonitorData bitmapCountData = BitmapMonitor.dumpBitmapCount();
        Log.d("bitmapmonitor", "bitmapCountData: " + bitmapCountData);

dumpBitmapInfo 会返回内存中一切图片的信息,假如只想获取到图片的总数和内存总量,能够调用 dumpBitmapCount,速度更快更轻量。

总结

这篇文章介绍了最新开源的图片内存剖析东西 Android Bitmap Monitor 的功用与中心 API,能够看到,它供给了很多图片的信息,咱们能够用它干什么呢?

现在想到这些运用场景:

  1. 大图报警: 一旦线上呈现过大的图片加载,能够上报一条日志,告诉开发人员查看
  2. 图片走漏监控:在页面退出后图片内存没有下降,能够看看是什么图片走漏了,哪里代码导致的
  3. 重复加载图片:相同的图片屡次 decode,没有利用好内存缓存

经过这个库咱们能够对 APP 的图片运用情况有更深的了解,也能够让知识面更广一点,今后面试聊到内存优化时能够不用忧虑只会讲 Java 内存了哈哈!还在等什么,快来运用吧!

假如对你有协助,欢迎点一个 star,感谢: github.com/shixinzhang…