在后台线程上将Glide缓存图像保存到磁盘

13

我希望使用Glide来预加载图片并将其缓存到磁盘以备将来使用。我想从后台线程调用此功能。

我已阅读了Glide的缓存文档,但它没有解释如何在没有实际目标的情况下下载图像。然后我发现了这个问题,并尝试使用类似的方法,但无论我尝试什么,都会出现此异常:

java.lang.IllegalArgumentException: You must call this method on the main thread

那么,我该如何告诉Glide在后台线程中缓存图像?

编辑:我真的想在后台线程上调用Glide的方法。我知道可以使用Handler和其他方式将其卸载到UI线程,但这不是我要问的。


为什么不下载ImageURLs并将其存储在Room DB中,每当需要时,您可以从该DB加载图像。 - Ümañg ßürmån
@UmangBurman,在数据库中存储图像(就像存储其他大型二进制对象一样)是一个不好的想法。我可以下载图像,将其存储在本地并保留本地URI,但这将等同于重新发明轮子。首先,我想知道Glide是否能够实现这一点。 - Vasiliy
4个回答

16
GlideApp.with(context)
    .downloadOnly()
    .diskCacheStrategy(DiskCacheStrategy.DATA) // Cache resource before it's decoded
    .load(url)
    .submit(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
    .get() // Called on background thread

正是我一直在寻找的。它甚至可以阻塞线程,真是太棒了。谢谢。 - Vasiliy

3
如果想在后台线程中将图像加载到缓存中以备将来使用,那么Glide就有这个功能。以下是操作步骤:
 //here i passing application context so our glide tie itself with application lifecycle

FutureTarget<File> future = Glide.with(getApplicationContext()).downloadOnly().load("your_image_url").submit();

如果您想检索要存储在数据库中的保存路径,则可以执行以下操作:

File file = future.get();
String path = file.getAbsolutePath();

你可以只用一行代码返回一个路径字符串,如下所示。
String path = Glide.with(getApplicationContext()).downloadOnly().load("your_image_url").submit().get().getAbsolutePath();

感谢您详细的回答。虽然您的回答是正确的,但我决定接受另一个答案,因为在这种情况下使用“DATA”缓存策略是强制性的。 - Vasiliy

0

我理解这个问题了吗?

private class update extends AsyncTask<Void, Void, Void> {

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }

    @Override
    protected Void doInBackground(Void... params) {
        try {
        RequestOptions options = new RequestOptions()
        .diskCacheStrategy(DiskCacheStrategy.ALL) // Saves all image resolution
        .centerCrop()
        .priority(Priority.HIGH)
        .placeholder(R.drawable.null_image_profile)
        .error(R.drawable.null_image_profile);

    Glide.with(context).load(imageUrl)
        .apply(options);

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    protected void onPostExecute(Void aVoid) {
        //finish
    }
}

不行。我没有profileImage,但即使我有一个,对后台线程调用into也会抛出异常。 - Vasiliy

0
你必须在主线程上调用此方法。
无论何时,当你调用使用Glide或从后台执行某些操作的方法时,请在内部运行:
runOnUiThread(new Runnable() {
                @Override
                public void run() {

              // Here, use glide or do your things on UiThread

            }
        });

在主线程中使用它,然后错误应该消失。


谢谢,但那不是我问的。我想知道如何从后台线程调用Glide的方法,而不是跳回UI线程。 - Vasiliy
没错!我刚看到你的编辑。但是问题是,“Glide影响UI效果”,因为它是一个图片加载库。所以,无论你想要实现什么,它都会像现在一样抛出异常。 - ʍѳђઽ૯ท

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