Android 从本地或远程加载的Glide ModelLoader

Android 从本地或远程加载的Glide ModelLoader,android,android-image,android-glide,Android,Android Image,Android Glide,我有一个自定义的滑动模型来计算图像的中心裁剪。相同的模型用于从服务器和本地存储获取图像 以下是模型界面: interface CenterCropImageInformation { fun getCenterCropUri(context: Context, @Px width: Int, @Px height: Int): Uri } 下面是它的ModelLoader,它从BaseGlideUrlLoader扩展而来: class CenterCropImageInformatio

我有一个自定义的滑动模型来计算图像的中心裁剪。相同的模型用于从服务器和本地存储获取图像

以下是模型界面:

interface CenterCropImageInformation {
    fun getCenterCropUri(context: Context, @Px width: Int, @Px height: Int): Uri
}
下面是它的ModelLoader,它从
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() {}
    }
}
class CenterCropImageInformationLoader私有构造函数(
上下文:上下文,
混凝土加载器:模型加载器,
modelCache:modelCache?
):BaseGlideUrlLoader(concreteLoader、modelCache){
私有val applicationContext:Context=Context.applicationContext
覆盖有趣的getUrl(
型号:CenterCropImageInformation,宽度:Int,
高度:Int,选项:选项
):字符串{
return model.getCenterCropUri(applicationContext,width,height).toString()
}
覆盖有趣的句柄(centerCropImageInformation:centerCropImageInformation):布尔值{
返回真值
}
/**
*[CenterCropImageInformation]的默认工厂。
*/
阶级工厂(
私有val应用上下文:上下文,
私有val模型缓存:模型缓存?
):ModelLoaderFactory{
覆盖有趣的构建(
多因素:多因素工厂
):ModelLoader{
val modelLoader=multiFactory.build(GlideUrl::class.java,InputStream::class.java)
return CenterCropImageInformationLoader(applicationContext、modelLoader、modelCache)
}
覆盖有趣的拆卸(){}
}
}
这适用于具有
http/https
方案的图像,但不适用于用于从本地设备存储加载图像的
file
方案

我查看了Glide的源代码,最接近的ModelLoader听起来像是一个选项,它是
UriLoader
,但问题是它不支持自定义模型。它只支持
Uri


最佳的解决方案是使用一个与Glide捆绑在一起的预先存在的ModelLoader,但是除非我错过了它,否则我找不到任何适合我需要的。如果真是这样的话,我该如何实现这样的ModelLoader呢?

我读了之后就明白了。关键是将加载委托给知道如何处理
文件
http/https
方案的ModelLoader

我要做的是直接实现
ModelLoader
接口,而不是扩展
BaseGlideUrlLoader
。我们已经知道Glide的内置
UriLoader
可以处理
文件
http/https
方案,所以我们将其委托给它。现在,为了获得
UriLoader
的实例,我们使用传递给我们工厂的
build
方法的
multivelloaderfactory
。默认滑动配置为
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() {}
     }
}
类中心CropimageInformationLoader(
私有val模型加载器:模型加载器,
私有val modelCache:modelCache
):ModelLoader{
覆盖buildLoadData(
型号:CenterCropImageInformation,
宽度:Int,
高度:Int,
选项:选项
):ModelLoader.LoadData{
val-uri:uri=modelCache.get(model,width,height)?:model.getUri(model,width,height)
放置(模型、宽度、高度、uri)
返回modelLoader.buildLoadData(uri、宽度、高度、选项)
}
覆盖有趣的句柄(型号:CenterCropImageInformation):布尔值=真
阶级工厂(
私有val应用上下文:上下文,
私有val modelCache:modelCache
):ModelLoaderFactory{
覆盖有趣的构建(
多因素:多因素工厂
):ModelLoader{
val modelLoader=multiFactory.build(Uri::class.java,InputStream::class.java)
return CenterCropImageInformationLoader(applicationContext、modelLoader、modelCache)
}
覆盖有趣的拆卸(){}
}
}
正如我们所看到的,我们不再扩展
baseglideurloader
。相反,我们实现了
ModelLoader
接口,在
buildLoadData()
实现中,我们尝试从缓存中获取URI(这类似于
BaseGlideUrlLoader
正在做的事情),然后在传递给构造函数的
ModelLoader
上调用
buildLoadData(),这恰好是我前面提到的
UriLoader
的一个实例,多亏了
multivelloaderfactory


这种类型的ModelLoader不是Glide内置model Loader的一部分,这真是令人惊讶。

感谢您发布解决方案!