Android-图片加载卡顿优化

1,349 阅读2分钟

图片加载导致的卡顿

图片(包括帧动画)页面渲染过多导致卡顿,在不改变图片大小、质量情况下可以这样优化:

  1. 子线程加载图片。图片的加载是不要求线程的,因此可以将其放在子线程加载,将加载后的Drawable、Bitmap再设置到view上
  2. 在设置图片时,使用view.post()。这种处理是通过handler避免直接set图片导致卡主线程,

    个人理解:view完整绘制流程特别是图片加载涉及很多handler调用,如果直接set图片会在前一个图片加载过程中直接开始自己的加载从而导致卡顿(注意加载不是直接渲染,渲染是子线程的。这是指主线程会加载图片的信息),而view.post()是通过handler是以队列方式前面的处理完下一个再开始,从而可以避免导致的卡顿情况。

  3. 图片过多,看是否可以合并,避免多次加载。
  4. 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