从本地或远程加载的 Glide ModelLoader
Glide ModelLoader that loads either from local or remote
我有一个自定义 Glide 模型来计算图像的中心裁剪。相同的模型用于从服务器和本地存储获取图像。
模型界面如下:
interface CenterCropImageInformation {
fun getCenterCropUri(context: Context, @Px width: Int, @Px height: Int): Uri
}
这是从 BaseGlideUrlLoader
:
扩展而来的模型加载器
class CenterCropImageInformationLoader private constructor(
context: Context,
concreteLoader: ModelLoader<GlideUrl, InputStream>,
modelCache: ModelCache<CenterCropImageInformation, GlideUrl>?
) : BaseGlideUrlLoader<CenterCropImageInformation>(concreteLoader, modelCache) {
private val applicationContext: Context = context.applicationContext
override fun getUrl(
model: CenterCropImageInformation, width: Int,
height: Int, options: Options
): String {
return model.getCenterCropUri(applicationContext, width, height).toString()
}
override fun handles(centerCropImageInformation: CenterCropImageInformation): Boolean {
return true
}
/**
* The default factory for [CenterCropImageInformation]s.
*/
class Factory(
private val applicationContext: Context,
private val modelCache: ModelCache<CenterCropImageInformation, GlideUrl>?
) : ModelLoaderFactory<CenterCropImageInformation, InputStream> {
override fun build(
multiFactory: MultiModelLoaderFactory
): ModelLoader<CenterCropImageInformation, InputStream> {
val modelLoader = multiFactory.build(GlideUrl::class.java, InputStream::class.java)
return CenterCropImageInformationLoader(applicationContext, modelLoader, modelCache)
}
override fun teardown() {}
}
}
这适用于 http/https
方案的图像,但不适用于 file
方案 - 用于从本地设备存储加载图像的方案。
我查看了 Glide 的源代码,最接近的听起来像是一个选项的 ModelLoader 是 UriLoader
,但问题是那个不支持自定义模型。只支持Uri
.
最佳解决方案是使用与 Glide 捆绑在一起的预先存在的 ModelLoader,但除非我错过了它,否则我找不到任何适合我需要的东西。如果真是这样,我该如何实现这样的ModelLoader?
看完Glide's ModelLoaders tutorial就明白了。关键是将加载委托给知道如何处理 file
和 http/https
方案的 ModelLoader。
我要做的是直接实现 ModelLoader
接口而不是扩展 BaseGlideUrlLoader
。我们已经知道 Glide 的内置 UriLoader
可以处理 file
和 http/https
方案,所以我们委托给它。现在要获取 UriLoader
的实例,我们使用传递给我们工厂的 build
方法的 MultiModelLoaderFactory
。默认的 Glide 配置为 Uri
+ InputStream
对注册 UriLoader
。
class CenterCropImageInformationLoader(
private val modelLoader: ModelLoader<Uri, InputStream>,
private val modelCache: ModelCache< CenterCropImageInformation, Uri>
) : ModelLoader<CenterCropImageInformation, InputStream> {
override fun buildLoadData(
model: CenterCropImageInformation,
width: Int,
height: Int,
options: Options
): ModelLoader.LoadData<InputStream>? {
val uri: Uri = modelCache.get(model, width, height) ?: model.getUri(model, width, height)
modelCache.put(model, width, height, uri)
return modelLoader.buildLoadData(uri, width, height, options)
}
override fun handles(model: CenterCropImageInformation): Boolean = true
class Factory(
private val applicationContext: Context,
private val modelCache: ModelCache<CenterCropImageInformation, Uri>
) : ModelLoaderFactory<CenterCropImageInformation, InputStream> {
override fun build(
multiFactory: MultiModelLoaderFactory
): ModelLoader<CenterCropImageInformation, InputStream> {
val modelLoader = multiFactory.build(Uri::class.java, InputStream::class.java)
return CenterCropImageInformationLoader(applicationContext, modelLoader, modelCache)
}
override fun teardown() {}
}
}
如我们所见,我们不再扩展 BaseGlideUrlLoader
。相反,我们实现了 ModelLoader
接口,在 buildLoadData()
实现中,我们尝试从缓存中获取 URI(这类似于 BaseGlideUrlLoader
所做的),然后我们调用 buildLoadData()
我们传递给构造函数的 ModelLoader
恰好是 UriLoader
的一个实例,正如我之前提到的,感谢 MultiModelLoaderFactory
.
令人惊讶的是,这种类型的 ModelLoader 不是 Glide 内置模型加载器的一部分。
我有一个自定义 Glide 模型来计算图像的中心裁剪。相同的模型用于从服务器和本地存储获取图像。
模型界面如下:
interface CenterCropImageInformation {
fun getCenterCropUri(context: Context, @Px width: Int, @Px height: Int): Uri
}
这是从 BaseGlideUrlLoader
:
class CenterCropImageInformationLoader private constructor(
context: Context,
concreteLoader: ModelLoader<GlideUrl, InputStream>,
modelCache: ModelCache<CenterCropImageInformation, GlideUrl>?
) : BaseGlideUrlLoader<CenterCropImageInformation>(concreteLoader, modelCache) {
private val applicationContext: Context = context.applicationContext
override fun getUrl(
model: CenterCropImageInformation, width: Int,
height: Int, options: Options
): String {
return model.getCenterCropUri(applicationContext, width, height).toString()
}
override fun handles(centerCropImageInformation: CenterCropImageInformation): Boolean {
return true
}
/**
* The default factory for [CenterCropImageInformation]s.
*/
class Factory(
private val applicationContext: Context,
private val modelCache: ModelCache<CenterCropImageInformation, GlideUrl>?
) : ModelLoaderFactory<CenterCropImageInformation, InputStream> {
override fun build(
multiFactory: MultiModelLoaderFactory
): ModelLoader<CenterCropImageInformation, InputStream> {
val modelLoader = multiFactory.build(GlideUrl::class.java, InputStream::class.java)
return CenterCropImageInformationLoader(applicationContext, modelLoader, modelCache)
}
override fun teardown() {}
}
}
这适用于 http/https
方案的图像,但不适用于 file
方案 - 用于从本地设备存储加载图像的方案。
我查看了 Glide 的源代码,最接近的听起来像是一个选项的 ModelLoader 是 UriLoader
,但问题是那个不支持自定义模型。只支持Uri
.
最佳解决方案是使用与 Glide 捆绑在一起的预先存在的 ModelLoader,但除非我错过了它,否则我找不到任何适合我需要的东西。如果真是这样,我该如何实现这样的ModelLoader?
看完Glide's ModelLoaders tutorial就明白了。关键是将加载委托给知道如何处理 file
和 http/https
方案的 ModelLoader。
我要做的是直接实现 ModelLoader
接口而不是扩展 BaseGlideUrlLoader
。我们已经知道 Glide 的内置 UriLoader
可以处理 file
和 http/https
方案,所以我们委托给它。现在要获取 UriLoader
的实例,我们使用传递给我们工厂的 build
方法的 MultiModelLoaderFactory
。默认的 Glide 配置为 Uri
+ InputStream
对注册 UriLoader
。
class CenterCropImageInformationLoader(
private val modelLoader: ModelLoader<Uri, InputStream>,
private val modelCache: ModelCache< CenterCropImageInformation, Uri>
) : ModelLoader<CenterCropImageInformation, InputStream> {
override fun buildLoadData(
model: CenterCropImageInformation,
width: Int,
height: Int,
options: Options
): ModelLoader.LoadData<InputStream>? {
val uri: Uri = modelCache.get(model, width, height) ?: model.getUri(model, width, height)
modelCache.put(model, width, height, uri)
return modelLoader.buildLoadData(uri, width, height, options)
}
override fun handles(model: CenterCropImageInformation): Boolean = true
class Factory(
private val applicationContext: Context,
private val modelCache: ModelCache<CenterCropImageInformation, Uri>
) : ModelLoaderFactory<CenterCropImageInformation, InputStream> {
override fun build(
multiFactory: MultiModelLoaderFactory
): ModelLoader<CenterCropImageInformation, InputStream> {
val modelLoader = multiFactory.build(Uri::class.java, InputStream::class.java)
return CenterCropImageInformationLoader(applicationContext, modelLoader, modelCache)
}
override fun teardown() {}
}
}
如我们所见,我们不再扩展 BaseGlideUrlLoader
。相反,我们实现了 ModelLoader
接口,在 buildLoadData()
实现中,我们尝试从缓存中获取 URI(这类似于 BaseGlideUrlLoader
所做的),然后我们调用 buildLoadData()
我们传递给构造函数的 ModelLoader
恰好是 UriLoader
的一个实例,正如我之前提到的,感谢 MultiModelLoaderFactory
.
令人惊讶的是,这种类型的 ModelLoader 不是 Glide 内置模型加载器的一部分。