编程知识 cdmana.com

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)
    }
}
複制代碼

版权声明
本文为[流沙三七]所创,转载请带上原文链接,感谢
https://cdmana.com/2021/11/20211125175017698z.html

Tags glide 解决
Scroll to Top