从本地或远程加载的Glide ModelLoader

时间:2019-03-22 22:16:00

标签: android android-image android-glide

我有一个自定义的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?

1 个答案:

答案 0 :(得分:1)

我在读完Glide's ModelLoaders tutorial之后才知道。关键是通过将加载委托给知道如何处理filehttp/https方案的ModelLoader。

我要做的是直接实现ModelLoader接口,而不是扩展BaseGlideUrlLoader。我们已经知道Glide的内置UriLoader可以处理filehttp/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内置模型加载器的一部分,实在令人惊讶。