使用 Glide 从 Firebase 下载图像 - 如何实现超时?

问题描述 投票:0回答:1

我成功使用 Glide 从 Firebase 下载图像。

我有我的标准 GlideModule:

@GlideModule
public class MyGlideModule extends AppGlideModule {

    @Override
    public void registerComponents(Context context, Glide glide, Registry registry) {
        // Register FirebaseImageLoader to handle StorageReference
        registry.append(StorageReference.class, InputStream.class,
                new FirebaseImageLoader.Factory());
    }
}

然后在我的活动中:

GlideApp.with(this /* context */)
        .load(storageReference)
        .diskCacheStrategy(DiskCacheStrategy.NONE)
        .skipMemoryCache(true)
        .fitCenter()
        .error(R.drawable.broken)
        .transition(DrawableTransitionOptions.withCrossFade(2000))
        .listener(new RequestListener<Drawable>() {
            @Override
            public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
                Log.i("Info","Load failed");
                return false;
            }

            @Override
            public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
                Log.i("Info","Load successful");
                return false;
            }
        })
        .into(imageView);

这通常工作正常,但当设备没有互联网连接时,图像视图保持空白 -

R.drawable.broken
错误图像不会被触发,并且
onLoadFailed
onResourceReady
都不会被触发。如果信号恢复,图像就会出现。

我想检测到这种情况正在发生,并向用户标记他们需要更好的信号。似乎最明显的方法是实施超时(因为似乎没有超时)。然而,简单地将

.timeout(3000)
添加到 Activity 部分是行不通的,因为在使用 GlideModule 时它会被忽略。我假设答案位于
FirebaseImageLoader.Factory()
设置中的某个地方,但我找不到任何文档,并且源代码中不清楚。

java android firebase firebase-storage android-glide
1个回答
0
投票

我来到这里是因为遇到了同样的需求,所以我很高兴在研究后分享我的想法。

通过

FirebaseImageLoader

 的构建器设置时,
Glide
不支持超时选项。您将需要创建自己的自定义加载程序或通过利用现有超时值来解决方法。

需要注意的是,Glide默认可以设置的超时是为了用于网络超时。

Glide
的超时存储在键入
HttpGlideUrlLoader.TIMEOUT
的选项中,您可以通过
RequestBuilder.getOptions().get(HttpGlideUrlLoader.TIMEOUT)
检索它。

如果您使用协程,我的解决方法建议如下:

suspendCoroutine { continuation ->
    addListener(
        object : RequestListener<T> {
            override fun onLoadFailed(
                ex: GlideException?,
                model: Any?,
                target: Target<T>?,
                isFirstResource: Boolean
            ): Boolean {
                continuation.resumeWithException(ex ?: RuntimeException())
                return false
            }

            override fun onResourceReady(
                resource: T,
                model: Any?,
                target: Target<T>?,
                dataSource: DataSource?,
                isFirstResource: Boolean
            ): Boolean {
                continuation.resume(resource)
                return false
            }
        }
    ).submit().get(timeoutMs, TimeUnit.MILLISECONDS)
}

如果是自定义加载程序,您可以使用现有的

FirebaseImageLoader
源作为基础并进行一些修改。加载程序了解 Glide 的选项,因此您可以从中获取超时并传递到 fetch 负责从 Firebase Storage 获取数据的位置并执行您自己的自定义处理,例如

FirebaseImageLoader

// ...
    ): ModelLoader.LoadData<InputStream> {
        val timeout = options.get(HttpGlideUrlLoader.TIMEOUT) ?: 2_500
        return ModelLoader.LoadData(
            FirebaseStorageKey(ref),
            FirebaseStorageFetcher(ref, timeout)
        )
    }
// ...

FirebaseStorageFetcher

// ...
    override fun loadData(priority: Priority, callback: DataFetcher.DataCallback<in InputStream>) {
        try {
            stream = Tasks
                .await(ref.stream.also { this.task = it }, timeout.toLong(), TimeUnit.MILLISECONDS)
                .stream
            callback.onDataReady(stream)
        } catch (ex: Exception) {
            callback.onLoadFailed(ex)
        }
    }
// ...

最后,将您自己的课程注册到您的

GlideModule

© www.soinside.com 2019 - 2024. All rights reserved.