Glide 加载图片闪烁问题解决

同一个 ImageView 切换图片显示时会闪现一下 placeHolder,如果 placeHolder 为空则会闪现一下背景,原因有两个:

  1. into 方法会取消上一次加载,最终会调用到 [Target.onLoadCleared] 方法,如果是直接 into(ImageView),则会把原来的图置空并设置 placeHolder, 如果是继承 [CustomViewTarget],则会接着调用到 [CustomViewTarget.onResourceLoading]
  2. [ImageViewTarget.onLoadStarted] 时会把原来的图置空并设置 placeHolder

但是有的场景是不希望用 placeHolder 的。所以需要一种选择加载中是否使用 placeHolder 的能力,如果 placeHolder 不为空,则会使用 placeHolder,为空则不使用,此时 ImageView 会显示上次加载的图,直到当前图加载完或加载失败。

abstract class SeamlessImageViewTarget<Z>(view: ImageView) : CustomViewTarget<ImageView, Z>(view), ViewAdapter {
    private var animatable: Animatable? = null

    override fun onStart() {
        animatable?.start()
    }

    override fun onStop() {
        animatable?.stop()
    }

    override fun getCurrentDrawable(): Drawable? = view.drawable

    override fun setDrawable(drawable: Drawable?) {
        view.setImageDrawable(drawable)
    }

    override fun onLoadFailed(errorDrawable: Drawable?) {
        setResourceInternal(null)
        setDrawable(errorDrawable)
    }

    override fun onResourceLoading(placeholder: Drawable?) {
        super.onResourceLoading(placeholder)
        // placeholder 为空则不设置,会显示上一张图
        placeholder?.let { setDrawable(placeholder) }
    }

    override fun onResourceReady(resource: Z, transition: Transition<in Z>?) {
        if (transition == null || !transition.transition(resource, this)) {
            setResourceInternal(resource)
        } else {
            maybeUpdateAnimatable(resource)
        }
    }

    override fun onResourceCleared(placeholder: Drawable?) {
        animatable?.stop()
        // placeholder 为空则不设置,会显示上一张图
        placeholder?.let { setDrawable(placeholder) }
    }

    private fun setResourceInternal(resource: Z?) {
        // Order matters here. Set the resource first to make sure that the Drawable has a valid and
        // non-null Callback before starting it.
        setResource(resource)
        maybeUpdateAnimatable(resource)
    }

    private fun maybeUpdateAnimatable(resource: Z?) {
        animatable = if (resource is Animatable) {
            resource.apply { start() }
        } else {
            null
        }
    }

    protected abstract fun setResource(resource: Z?)
}

class SeamlessBitmapImageViewTarget(view: ImageView) : SeamlessImageViewTarget<Bitmap>(view) {
    override fun setResource(resource: Bitmap?) {
        view.setImageBitmap(resource)
    }
}

class SeamlessDrawableImageViewTarget(view: ImageView) : SeamlessImageViewTarget<Drawable>(view) {
    override fun setResource(resource: Drawable?) {
        view.setImageDrawable(resource)
    }
}
复制代码

Guess you like

Origin juejin.im/post/7034417406244028423