【组件篇2】如何学习Glide

643 阅读4分钟

1 学习大纲

muyangmin.github.io/glide-docs-…

2 Glide加载

2.1 Glide加载问题

  1. 加载Uri
Uri.parse("res://" + context.packageName + "/" + drawableResId)

2.2 Glide缓存策略

缓存策略英文说明中文说明
DiskCacheStrategy ALLCaches remote data with both DATA and RESOURCE, and local data with RESOURCE only.使用data和RESOURCE缓存远程数据,仅使用RESOURCE缓存本地数据。
DiskCacheStrategy NONESaves no data to cache.不缓存
DiskCacheStrategy DATAWrites retrieved data directly to the disk cache before it's decoded.在解码之前将检索到的数据直接写入磁盘缓存。
DiskCacheStrategy RESOURCEWrites resources to disk after they've been decoded将资源解码后写入磁盘
DiskCacheStrategy AUTOMATICTries to intelligently choose a strategy based on the data source of the com.bumptech.glide.load.data.DataFetcher and the EncodeStrategy of the com.bumptech.glide.load.ResourceEncoder (if an com.bumptech.glide.load.ResourceEncoder is available).智能选择策略
boolean isResourceCacheableReturns true if this request should cache the final transformed resource.该请求缓存最终转换的资源,则返回true
boolean decodeCachedResourceReturns true if this request should attempt to decode cached resource data.该请求尝试解码缓存的资源数据,则返回true
boolean decodeCachedDataReturns true if this request should attempt to decode cached source data.该请求尝试解码缓存的源数据,则返回true

2.3 Glide 适配广色域

fun getRequestOptionsWithColorSpace(options: RequestOptions): RequestOptions {
    if (isSupportWCG()) {
        options.set(Downsampler.PREFERRED_COLOR_SPACE, PreferredColorSpace.DISPLAY_P3)
    } else {
        options.set(Downsampler.PREFERRED_COLOR_SPACE, PreferredColorSpace.SRGB)
    }
    return options
}

使用BitmapFactory

在 API 26 中,我们为 BitmapFactory.Option添加了inPreferredColorSpace,允许您为已解码的 Bitmap 文件指定目标色彩空间。假设您现在想要解码一个文件,那么您可以用下面的代码进行色彩管理

final BitmapFactory.Options options = new BitmapFactory.Options(); 
// Decode this file to sRGB color space. 
options.inPreferredColorSpace = ColorSpace.get(Named.SRGB); 
Bitmap bitmap = BitmapFactory.decodeFile(FILE_PATH, options);

使用ImageDecoder

在以下示例代码中,我们使用 ImageDecoder#decodeBitmap API 将图片转换为 sRGB 位图。


ImageDecoder.Source source =
        ImageDecoder.createSource(FILE_PATH);
try {
    bitmap = ImageDecoder.decodeBitmap(source,
            new ImageDecoder.OnHeaderDecodedListener() {
                @Override
                public void onHeaderDecoded(ImageDecoder decoder,
                        ImageDecoder.ImageInfo info,
                        ImageDecoder.Source source) {
                    decoder.setTargetColorSpace(ColorSpace.get(Named.SRGB));
                }
            });
} catch (IOException e) {
    // handle exception.
}

2.4 预加载

//提前加载

fun preloadIcon(context: Context?, iconUrl: String) {
	context?.let {
		Glide.with(it)
			.load(iconUrl)
			.diskCacheStrategy(DiskCacheStrategy.ALL)
			.preload()
	}
}

2.5 加载的对象是View,但不是ImageView

//加载view

val cardViewTarget = ShadowCardViewTarget(iconView)
Glide.with(this.context)
    .load(appIconUrl)
    .placeholder(R.drawable.snack_bar_ic_icon_default)
    .diskCacheStrategy(DiskCacheStrategy.ALL)
    .into(cardViewTarget)
class ShadowCardViewTarget(
    private val customView: ShadowCardView
) : CustomViewTarget<COUIShadowCardView, Drawable>(customView) {


    override fun onLoadFailed(errorDrawable: Drawable?) {

    }

    override fun onResourceCleared(placeholder: Drawable?) {

    }

    override fun onResourceReady(resource: Drawable, transition: Transition<in Drawable>?) {
        customView.background = resource
    }

}

2.7 加载Bitmap

//加载Bitmap

Glide.with(it).asBitmap().load(imageUrl)
	.into(object : CustomTarget<Bitmap?>() {
		override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap?>?) {
			setBackground(resource)
		}

		override fun onLoadCleared(placeholder: Drawable?) {
		}
	})

Glide加载遇到的缓存问题

解决方法可参考这两篇文章

juejin.cn/post/697068…

缓存机制 juejin.cn/post/702411…

解决方法 juejin.cn/post/684490…

3 Glide常见问题

3.1 Glide加载网络图片不显示

Glide在Android 9不再支持http协议,需将http换成https

【分析方法1】 单步调试,跟踪异常抛出的log如下

com.bumptech.glide.load.engine.GlideException: Failed to load resource
There was 1 root cause:
java.net.SocketTimeoutException(failed to connect to ******.com/***** (port 443) from /**.***.***.** (port 42792) after 10000ms: isConnected failed: ETIMEDOUT (Connection timed out))
 call GlideException#logRootCauses(String) for more detail

【原因分析1】 确认pb是否有返回,无返回的话,说明是服务端的问题

【解决方法1】 1.确认pb是否有返回

Failed to load resource
There was 1 root cause:
java.net.SocketTimeoutException(timeout h2 stream:read)
 call GlideException#logRootCauses(String) for more detail

【分析方法2】
打印异常时,通过GlideException#logRootCauses打印原因

3.2 Glide加载网络图片不显示

【分析方法】

  1. 添加如下监听
  2. 在onLoadFailed中增加断点,进行单步调试
.listener(object : RequestListener<Bitmap> {
    override fun onLoadFailed(
        e: GlideException?,
        model: Any?,
        target: Target<Bitmap>?,
        isFirstResource: Boolean
    ): Boolean {
        Log.i(tag, "onLoadFailed")
        e?.printStackTrace()
        return false
    }

    override fun onResourceReady(
        resource: Bitmap?,
        model: Any?,
        target: Target<Bitmap>?,
        dataSource: DataSource?,
        isFirstResource: Boolean
    ): Boolean {
        Log.i(tag, "onResourceReady")
        return false
    }

})
.into(object : BitmapThumbnailImageViewTarget(imageView) {
    override fun onLoadStarted(placeholder: Drawable?) {
        super.onLoadStarted(placeholder)
        Log.i(tag, "onLoadStarted")
    }

    override fun onLoadFailed(errorDrawable: Drawable?) {
    // 此处增加断点,进行单步调试,查看异常log
        super.onLoadFailed(errorDrawable)
        Log.i(tag, "onLoadFailed")
    }

    override fun onResourceReady(
        resource: Bitmap,
        transition: Transition<in Bitmap>?
    ) {
        super.onResourceReady(resource, transition)
        Log.i(tag, "onResourceReady transition")
    }

    override fun onLoadCleared(placeholder: Drawable?) {
        super.onLoadCleared(placeholder)
        Log.i(tag, "onLoadCleared transition")
    }
})

【原因分析】

  1. 从上述断点调试的log中,可以看到如下exception,原因为:秘钥链验证失败,导致加载资源失败。
  2. 此错误来自 SSL Handshake 库,因为 SDK 正在尝试向sdk.split.io调用 GET http 请求。一个可能的根本原因是设备时间与当前时间不一致。
com.bumptech.glide.load.engine.GlideException: Failed to load resource
There was 1 root cause:
com.bumptech.glide.load.HttpException(****-***.storage.wanyol.com==>Exception:Chain validation failed, status code: 400)
 call GlideException#logRootCauses(String) for more detail

查看Glide源码可知,该错误为:

private void notifyFailed() {
  setNotifiedOrThrow();
  GlideException e = new GlideException("Failed to load resource", new ArrayList<>(throwables));
  callback.onLoadFailed(e);
  onLoadFailed();
}

【解决方案】
1、调整手机的时间为当前正确时间,查看上述现象解决

3.3 GLide加载大图优化

针对高清图加载慢的问题,可以先加载缩略图,再加载高清图

private fun loadThumbnailAndFullImage(imageView: ImageView) {
	val thumbnailUrl = "https://example.com/thumbnail.jpg" // 替换为你的缩略图URL
	val fullImageUrl = "https://example.com/full_image.jpg" // 替换为你的高清图URL

	Glide.with(this)
		.load(fullImageUrl)
		.thumbnail(Glide.with(this).load(thumbnailUrl))
		.into(imageView)
}