图片加载导致的卡顿
图片(包括帧动画)页面渲染过多导致卡顿,在不改变图片大小、质量情况下可以这样优化:
- 子线程加载图片。图片的加载是不要求线程的,因此可以将其放在子线程加载,将加载后的Drawable、Bitmap再设置到view上
- 在设置图片时,使用
view.post()。这种处理是通过handler避免直接set图片导致卡主线程,个人理解:view完整绘制流程特别是图片加载涉及很多handler调用,如果直接set图片会在前一个图片加载过程中直接开始自己的加载从而导致卡顿(注意加载不是直接渲染,渲染是子线程的。这是指主线程会加载图片的信息),而
view.post()是通过handler是以队列方式前面的处理完下一个再开始,从而可以避免导致的卡顿情况。 - 图片过多,看是否可以合并,避免多次加载。
- window设置了背景图,Activity就无需重复设置了,否则相当于多设置了一遍。
图片层叠导致卡顿
工作问题:9个空间会层叠9张图导致ui渲染卡顿。
解决:经排查此非图片大小问题,而是Drawable对象过多导致多次重复canvas调用卡主线程,解决方式是使用LayerDrawable合并多个图片并转换为一个Bitmap。
//核心处理
fun drawImgList(images: List<String>?) {
if (checkUrlListIsChanged(images)) {
this.lastList = images
if (!images.isNullOrEmpty()) {
mScope.launch {
flowOf(images).map {
Array<Drawable>(images.size) {
var bitmapDrawable = cacheDrawable[images[it]]
if (bitmapDrawable == null) {
val resId = ImageLoad.getResIdByName(images[it], context)
val bitmap = BitmapFactory.decodeResource(resources, resId)
bitmapDrawable = BitmapDrawable(resources, bitmap)
cacheDrawable[images[it]] = bitmapDrawable
}
bitmapDrawable
}
}.map {
//核心在这,多张图合并到一张Bitmap上。
LayerDrawable(it).toBitmap(width,height, Bitmap.Config.ARGB_8888)
}.flowOn(Dispatchers.IO).collect {
this@ImagesDrawView.setImageBitmap(it)
}
}
} else {
this.setImageDrawable(null)
}
}
}
以上是我实际遇到的问题及处理方式。图片加载优化还有其他姿势包括:1.使用工具对图片无损压缩如转换为webp; 2.按分辨率、大小对图片进行压缩加载 ;3.服务端返回按分辨率或宽高处理后的图片; 等等,在保证实际业务前提下,能达到性能指标就行。
写在最后
欢迎关注本人的代码库:wuxu_future