【问题标题】:Glide - Save GIF to FileGlide - 将 GIF 保存到文件
【发布时间】:2018-11-12 18:33:10
【问题描述】:

旁注 - 虽然我的一些示例使用 Kotlin,但 Java 或 Kotlin 中的答案很有帮助。

我正在使用Commit Content API 创建一个 GIF 键盘。为此,我需要能够创建 .gif 文件。

我正在使用 Glide 从互联网上获取图像并将它们显示在 recyclerview 内的列表中。

对于 Glide 下载的每个图像,我必须使用该图像的数据创建一个 File 对象。

我看到了两种可以实现这一目标的方法。

1] 像这样创建一个覆盖onResourceReady 的侦听器。这种方法的问题是我不知道如何将 GifDrawable 转换为 .gif 文件,因为所有 Stack Overflow 帖子都在讨论如何将 Drawable 转换为文件:

    Glide.with(context)
            .asGif()
            .load(items[position])
            .listener(object : RequestListener<GifDrawable> {
                override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<GifDrawable>?, isFirstResource: Boolean): Boolean {
                    Log.d("VED-APP","Glide Load Failed")
                    return false
                }

                override fun onResourceReady(resource: GifDrawable?, model: Any?, target: Target<GifDrawable>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean {
                    //I need code to convert the GifDrawable to a File

                    return false
                }

            })
            .into(holder.imageView)

2] 将图像加载到ByteArray 或类似的位置。来自Glide - download and resize GIF into a file 帖子的示例 Java 代码可能如下所示。这段代码的问题在于

A] .into(width,height) 已弃用

B] 没有.toBytes 方法

C] 我不想指定 GIF 的尺寸 - 我只想使用原始尺寸。 (或者,至少,我想保留纵横比)

byte[] bytes = Glide.with(context)
                    .load(items[position])
                    .asGif()
                    .toBytes()
                    .into(250, 250)
                    .get();
file = new File(fileName);

FileOutputStream fileWriter = new FileOutputStream(file);
fileWriter.write(bytes);
fileWriter.flush();
fileWriter.close();

有人可以帮助我改进这两种方法中的任何一种,或者提出一种使用 Glide 将 GIF 转换为文件的新方法吗?

【问题讨论】:

    标签: java android kotlin gif android-glide


    【解决方案1】:

    如果您只需要内容提交 API 的 URI,更新 @Nhật Tôn 的解决方案可能会更好。

    我不知道@Nhật Tôn 的解决方案是否有效。但是,这是我现在使用的解决方案,它基于他们的解决方案。我的解决方案是在 Kotlin 中,但它可以很容易地转换为 Java。

    首先,我使用以下代码将图像加载到ImageView

    //items[position] is a string that represents a URL
    Glide.with(context)
            .load(items[position])
            .into(holder.imageView)
    

    然后我从ImageView 中获取GifDrawable 并将其写入File 对象。

    val byteBuffer = (holder.imageView.drawable as GifDrawable).buffer
    val gifFile = File(localDirectory, "test.gif")
    
    val output = FileOutputStream(gifFile)
    val bytes = ByteArray(byteBuffer.capacity())
    (byteBuffer.duplicate().clear() as ByteBuffer).get(bytes)
    output.write(bytes, 0 ,bytes.size)
    output.close()
    

    此解决方案的一个潜在问题是GifDrawable 在写入文件时可能会被修改。

    解决此问题的方法是在将GifDrawable 写入文件之前将其克隆:

    val newGifDrawable = ((holder.imageView.drawable).constantState.newDrawable().mutate()) as GifDrawable
    

    【讨论】:

      【解决方案2】:

      如果您不必将所有 gif 保存在一个特定位置和/或必须为 gif 命名,我建议您只使用 Glide 自动为您缓存的 gif。

      首先,在您的 OnBindViewHolder 方法中,只需像往常一样将 gif 加载到您的 imageview 中:

      Glide.with(this)
                  .load(items[position])
                  .apply(new RequestOptions()
                          // This is to cache all versions of the gif, whether low-res or original size
                          .diskCacheStrategy(DiskCacheStrategy.ALL))
                  .into(holder.imageView);
      

      并使用此方法在任何你想要的地方获取 uri:

      Glide.with(this)
                  // Actually it won't download another time if the file has been cached
                  .download(items[position])
                  .listener(new RequestListener<File>() {
                      @Override
                      public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<File> target, boolean isFirstResource) {
                          return false;
                      }
      
                      @Override
                      public boolean onResourceReady(File resource, Object model, Target<File> target, DataSource dataSource, boolean isFirstResource) {
                          //Use this uri for the Commit Content API
                          Uri uri = Uri.fromFile(resource);
                          return false;
                      }
                  })
                  .submit();
      

      【讨论】:

      • 是否可以将File 类型的resource 对象复制到另一个位置(即我的应用程序的内部存储?)
      • 更新 - 我尝试了这段代码,发现 Glide 返回的 resource 对象的文件名是:98d8777561c28b94d88db128f9bbb768704353b40a79b52e4ac63861289fc79e.0。那么我的问题是,我可以使用outputstream 将其写入 GIF 文件吗?
      • 是的,您可以使用类似于items[position] 的名称保存文件,以便您以后更容易检索。您可以在第一个代码块中添加.listener 运算符以将文件保存在此处,无需其他方法即可下载。
      猜你喜欢
      • 2020-09-15
      • 2018-11-12
      • 2014-12-22
      • 2016-09-12
      • 2017-11-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多