将图像缓存到本地,来自Google Firebase存储

12
我正在寻找一种方法,从谷歌Firebase平台的存储中缓存图像。目前,我可以下载图片并向用户显示这些图片,但我无法缓存它们并在没有互联网连接的情况下访问它们。可以离线访问数据库,因此我认为也应该有一种存储方式。我不想将每个单独的图像下载到存储中,因为那样我就需要每次检查图像是否仍然是最新的,而它可能已更改。以下是我能找到的一些链接,但没有答案回答我的问题。也许有人知道解决方法或完成它的方法。谢谢!
下载文件: https://firebase.google.com/docs/storage/android/download-files 缓存(离线)数据库: https://firebase.google.com/docs/database/android/offline-capabilities 更新 1 以下是我如何使用 Picasso“缓存”文件,我添加了一个活动来处理下载:
Picasso.with(getApplicationContext())
                            .load(uri.toString())
                            .networkPolicy(NetworkPolicy.OFFLINE)
                            .into(image1);

欢迎任何帮助。谢谢!


你可以自己缓存图片吗?LRU和其他类型。 - Shubhank
3个回答

9
很抱歉,Firebase SDK本身不提供图像缓存功能。但是有几个很棒的库可以为您完成此操作。它们可以在一行代码中下载图像,将其显示在ImageView中并进行缓存。只需请求Firebase获取图像下载URL并将其提供给图像缓存库即可。
例如,如果您选择Picasso作为缓存库,则可以使用以下方式:
storageRef.child("users/me/profile.png").getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
    @Override
    public void onSuccess(Uri uri) {
        // Got the download URL for 'users/me/profile.png'
        // Pass it to Picasso to download, show in ImageView and caching
        Picasso.with(context).load(uri.toString()).into(imageView);
    }
}).addOnFailureListener(new OnFailureListener() {
    @Override
    public void onFailure(@NonNull Exception exception) {
        // Handle any errors
    }
});

更新:要使用Picasso的磁盘缓存,您需要显式设置OkHttpDownloader。请参见如何在Picasso中使用磁盘缓存?


2
我已经按照您提供的方式尝试了Picasso。问题是,如果我在没有网络的情况下重新启动应用程序,则图像不会显示出来...我需要说些什么来存储这些图像吗?或者我需要获取存储权限吗? - Wladislaw
没错,有一个陷阱:要使用Picasso的磁盘缓存,您需要显式设置OkHttpDownloader。请看这里https://dev59.com/V2Ag5IYBdhLWcg3wG3wK - Aleksei Reshetnikov
3
Firebase存储与数据库是分开的,而这个setPersistenceEnabled(true)不起作用。我们正在研究内置缓存以启用离线使用案例(并提高性能),但我们目前还没有具体计划,因此我们建议在这种情况下使用图像加载库,例如Picaso,Glide和SDWebImage(iOS)。 - Mike McDonald
7
是的,但是要从缓存中获取文件,我需要指定它的原始URL,而这个URL只能从Firebase存储中获取。我是否漏掉了什么? - Aleksei Reshetnikov
1
当您存储图像时,会获得一个带有downloadURL的快照 - 将此URL存储在数据库中,而不是图像名称,这样您就不必执行storageRef.child("users/me/profile.png").getDownloadUrl()。 - N.J.
显示剩余7条评论

7

感谢 @ATom 的提醒。API 已更改,FirebaseUI 3.0 现在使用 Glide 4.x。以下是更新后的示例:

To load an image from a StorageReference, first register in your AppGlideModule:

@GlideModule
public class MyAppGlideModule 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());
    }
}

Then you can load a StorageReference into an ImageView:

// Reference to an image file in Cloud Storage
StorageReference storageReference = ...;

// ImageView in your Activity
ImageView imageView = ...;

// Download directly from StorageReference using Glide
// (See MyAppGlideModule for Loader registration)
GlideApp.with(this /* context */)
        .load(storageReference)
        .into(imageView);

不要忘记在你的 build.gradle 中添加依赖:

implementation 'com.firebaseui:firebase-ui-:3.1.0'

GitHub上的答案源代码

新回答:

FirebaseUI 1.0 已经发布。存储示例中有一个名为FirebaseImageLoader的类。

使用 FirebaseImageLoader 显示的图像通过其在 Firebase Storage 中的路径进行缓存,因此重复加载速度快,可以节省带宽。

    // Reference to an image file in Firebase Storage
    StorageReference storageReference = ...;

    // ImageView in your Activity
    ImageView imageView = ...;

    // Load the image using Glide
    Glide.with(this /* context */)
            .using(new FirebaseImageLoader())
            .load(storageReference)
            .into(imageView);

这个答案仅适用于Glide 3.X和旧版本的FirebaseUI。在Glide 4.X中已经没有使用(using())这个方法了。 - ATom
如果拍摄了新照片,这个方法能离线工作吗? - VivekRajendran
@VivekRajendran 不,它不会处理这些情况,你需要自己处理。 - Dmytro Rostopira
你如何限制缓存大小?我使用了这个实现,它完美地工作,但当缓存大小开始增长时,应用程序开始需要30秒来加载数据。 - King Of The Jungle
1
@Records https://github.com/bumptech/glide/wiki/Configuration#disk-cache@记录 https://github.com/bumptech/glide/wiki/Configuration#disk-cache - Dmytro Rostopira

2
我有同样的问题。尝试了所有可能的方法,但无法解决。我认为问题在于Firebase存储生成的链接。Picasso通常会缓存它加载的图像。我尝试过其他云服务,如Cloudinary、LibPixel,它们的链接以图像格式结尾(例如:.jpg),而Picasso缓存这些链接中的图像。而Firebase的链接以令牌号码结尾,这很奇怪,它会失败!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接