我有一个自定义的Glide模型来计算图像的中心裁剪。相同的模型用于从服务器以及本地存储中获取图像。
这是模型界面:
interface CenterCropImageInformation {
fun getCenterCropUri(context: Context, @Px width: Int, @Px height: Int): Uri
}
这是从BaseGlideUrlLoader
扩展来的ModelLoader:
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?
答案 0 :(得分:1)
我在读完Glide's ModelLoaders tutorial之后才知道。关键是通过将加载委托给知道如何处理file
和http/https
方案的ModelLoader。
我要做的是直接实现ModelLoader
接口,而不是扩展BaseGlideUrlLoader
。我们已经知道Glide的内置UriLoader
可以处理file
和http/https
方案,因此我们将其委托给它。现在,要获取UriLoader
的实例,我们使用传递到工厂的MultiModelLoaderFactory
方法的build
。对于UriLoader
+ Uri
对,默认的Glide配置寄存器InputStream
。
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
的一个实例。
这种类型的ModelLoader不属于Glide内置模型加载器的一部分,实在令人惊讶。