大图监控
内存大户Bitmap大图检测:
对加载图片时所占用的内存大小设置一个阈值,当图片超过这个阀值的时候进行信息提示给RD。
图片的来源可以是本地图片,网络图片。比如网络图片,当我们请求服务器返回图片的时候,图片的大小我们是不知道的,尤其是运营模块中包含大量的图片资源,很容易出现OOM。我们可以在开发阶段使用大图监控功能来识别那些超标的图片,提示给RD.
在Release环境下可以将报警信息上报到服务器,实时观察数据,有问题及时处理。
但是一些资源文件如layout、drawable等如果同名则下层会被上层覆盖,这时layout里view的id发生了变化就可能导致空指针的问题。为了避免这种问题,我们写了一个Gradle插件通过hook MergeResource这个Task,拿到所有library和主库的资源文件,如果检查到重复则会中断编译过程,输出重复的资源名及对应的library name,同时避免有些资源因为样式等原因确实需要覆盖,因此我们设置了白名单。同时在这个过程中我们也拿到了所有的的图片资源,可以顺手做图片大小的本地监控.
大图监控实现原理:
参考:https://developer.aliyun.com/article/913730
请求网络图片的时候可以在url中拼接ImageView的宽高大小请求csdn缓存服务器返回对应的图片,
优势是首先节省了传输带宽流量,其次降低了客户端处理图片的cpu资源消耗.
项目中使用Glide加载图片和没有使用Glide加载图片两种情况监控
1.没有使用Glide加载图片:
使用AspectJ hook BitMapFactory的decodeResouse(R.id),decodeFile(File),decodeStream(url)等相关图片加载函数,
根据生成的bitmap内存占用大小超过设置的内存大小阀值时收集图片信息报警弹窗提示给RD。
超过阀值的图片获取图片的信息:图片的网络地址,名称,占用内存大小,分辨率大小等信息通过弹窗的方式提示给RD.
具体做法是使用AspectJ检查decodeResourse(),decodeFile(),decodeStream()这些函数返回值都是Bitmap对象,拿到这个Bitmap对象可以获取图片占用内存的大小。Bitmap不能获取图片文件物理大小,只能获取加载到内存后占据内存的大小
2.使用Glide加载图片:
理论上来说使用Glide加载图片,本身对图片已经进行了压缩处理,但可能压缩处理后图片资源占据的内存大小依然很大。
采用Gradle自定义插件+Android Library的形式。
2.1 largeimage-plugin:自定义Gradle插件,主要负责将我们编写的字节码插入到class文件。
2.2 largeimage:Andriod Library,主要负责将获取到的图片数据进行过滤,保存超标图片并且以弹窗呈现给用户。
LargeImageTransform:主要负责对Glide进行字节码操作,
阅读Glide源码,找到Glide hook点
Glide在获取图片资源成功以后会在SingleRequest类的requestListeners.onResourceReady(Bitmap map)触发回调,
1.自定义Transform的方式扫描所有的字节码Class文件,
然后使用ASM扫描SingleRequest类获取 requestListeners,在字节码文件中插入Android Library中自定义listener。
2.这时候就可以获得 加载完图片以后的回调,插入Android Library获取图片大小检测逻辑字节码。
使用这种方式同时可以扩展使用Picasso,Fresco,ImageLoader框架加载图片的内存验证。