Glide ModelLoader, который загружается с локального или удаленного - PullRequest
0 голосов
/ 23 марта 2019

У меня есть пользовательская модель Glide, чтобы рассчитать центральную обрезку для изображения.Та же модель используется для получения изображений с сервера, а также из локального хранилища.

Вот интерфейс модели:

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() {}
    }
}

Это прекрасно работает для изображений со схемой http/https, но не работает для схемы file - той, которая используется для загрузки изображений из локального хранилища устройства.

У меня былПосмотрите на исходный код Glide и ближайший ModelLoader, который звучит как опция UriLoader, но проблема в том, что он не поддерживает пользовательские модели.Он поддерживает только Uri.

. Оптимальным решением было бы использование уже существующего ModelLoader, который входит в комплект поставки Glide, но если я не пропустил его, я не смог найти ни одного, соответствующего моим потребностям.Если это действительно так, как мне реализовать такой ModelLoader?

1 Ответ

1 голос
/ 25 марта 2019

Я понял это после прочтения Учебник Glide's ModelLoaders . Ключ заключается в делегировании загрузки ModelLoader, который знает, как обрабатывать схемы file и http/https.

Что мне нужно было сделать, это реализовать интерфейс ModelLoader напрямую вместо расширения BaseGlideUrlLoader. Мы уже знаем, что встроенная в Glide UriLoader может обрабатывать схемы file и http/https, поэтому мы делегируем ее. Теперь, чтобы получить экземпляр UriLoader, мы используем MultiModelLoaderFactory, который передается методу build нашей фабрики. Конфигурация Glide по умолчанию регистрируется UriLoader для Uri + 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, как я упоминал ранее, благодаря MultiModelLoaderFactory.

Удивительно, что этот тип ModelLoader не входит в состав встроенных загрузчиков моделей Glide.

...