如何获取文件(png、jpg、pdf 等)的缩略图?

huangapple go评论62阅读模式
英文:

How do I get a thumbnail of a file (png, jpg, pdf, etc.)?

问题

我正在进行一个简单的文件管理器作为学习项目。我有一个问题,如何获取文件的缩略图以在RecyclerView列表中显示它?

我还想知道java.io.File是否有唯一的ID?我需要在本地存储中缓存文件并比较自上次启动应用以来哪些文件发生了变化。

英文:

I am working on a simple file manager as a learning project. And I have a question how can I get the thumbnail of a file to display it in the RecyclerView list?

I'm also interested in whether java.io.File has a unique ID? I need to cache files in the local storage and compare which ones have changed since the app was last launched.

答案1

得分: 1

You should use something like Glide anyway, that's the standard recommendation and it will automatically scale images to fit your ImageViews, run it concurrently so it's not blocking the main thread, do caching etc.

这样的话,你应该使用类似 Glide 的东西,这是标准建议,它会自动缩放图像以适应你的 ImageView,并并行运行以避免阻塞主线程,还会进行缓存等操作。

This is especially important for things like RecyclerViews where you might be scrolling through a lot of images quickly - not only does it need to be performant, you need to make sure old requests for a given ViewHolder are cancelled so it doesn't end up displaying the wrong image for the current item (since ViewHolders are reused when scrolling). Libraries like Glide handle this for you!

这对于像 RecyclerView 这样的东西尤其重要,你可能会快速滚动浏览很多图像 - 它不仅需要高性能,还需要确保取消对给定 ViewHolder 的旧请求,以免显示当前项的错误图像(因为滚动时会重复使用 ViewHolder)。像 Glide 这样的库会为你处理这些!

In some cases where you're using Intents to fetch images, you'll get a thumbnail Bitmap in the result Intent (example) while the actual image is accessed via a provided URL. So in those cases, that might be a useful way to display a thumbnail (not in your case, just mentioning it as a good thing to know! Just use Glide etc.)

在某些情况下,当你使用 Intent 来获取图像时,你会在结果 Intent 中获取到缩略图 Bitmap示例),而实际的图像是通过提供的 URL 访问的。因此,在这些情况下,这可能是一种有用的显示缩略图的方式(不适用于你的情况,只是提到这是一个有用的知识点!只需使用 Glide 等)。

Your other question is a different one. I'm not sure if File gives you access to a specific reference determined by the filesystem, but even if it did that wouldn't tell you if that file object had changed. You can register a path with a WatchService to watch for changes, but that only works while your app is running obviously.

你的另一个问题与此不同。我不确定 File 是否提供了访问文件系统确定的特定引用,但即使提供了,也不能告诉你文件对象是否发生了更改。你可以使用 WatchService 注册一个路径来监视更改,但显然只在你的应用程序运行时有效。

To look for changes since the app was last run, you'd have to store some state and compare it to the current state. Maybe mapping Path#hashCode to File#lastModified, and looking for changes to that (as well as new files without a path entry, and maybe path entries with no corresponding file). Or you could store checksums for files, using MD5 or something.

要查找自上次运行应用以来的更改,你需要存储一些状态并将其与当前状态进行比较。也许将 Path#hashCode 映射到 File#lastModified,并查找对此的更改(以及没有路径条目的新文件,以及可能没有相应文件的路径条目)。或者你可以为文件存储校验和,使用 MD5 或其他方法。

You'd probably want to handle this in a repository or something. So your app requests the list of files for a particular directory from the repo, and that handles fetching them from disk, loading the old state, comparing the files and sticking them in a data structure (e.g. a data class that holds the path, updated status etc), updating the stored state, and firing off the data to the requester.

你可能想在仓库或其他地方处理这个问题。因此,你的应用程序会从仓库请求特定目录的文件列表,仓库会负责从磁盘中获取它们,加载旧状态,比较文件并将它们存储在数据结构中(例如,一个包含路径、更新状态等的数据类),更新存储的状态,并将数据发送给请求者。

If you want to know more about the repository pattern, have a look at this guide: Data layer. The idea is your list view requests data for a particular directory, puts in a request from a repo component, and gets the data delivered later (usually getting a Flow that's handled in a coroutine). Accessing the disk is quite heavy, which is why it needs to be done concurrently (Glide takes care of this for you, which is why it's nice, but it's only for loading images!)

如果你想了解更多关于仓库模式的信息,请查看这个指南:数据层。这个想法是你的列表视图请求特定目录的数据,从仓库组件发出请求,然后稍后获取数据(通常获取一个在协程中处理的 Flow)。访问磁盘是相当重的,这就是为什么需要并发执行(Glide 为你处理了这一点,这就是为什么它很好,但只用于加载图像!)

英文:

You should use something like Glide anyway, that's the standard recommendation and it will automatically scale images to fit your ImageViews, run it concurrently so it's not blocking the main thread, do caching etc.

This is especially important for things like RecyclerViews where you might be scrolling through a lot of images quickly - not only does it need to be performant, you need to make sure old requests for a given ViewHolder are cancelled so it doesn't end up displaying the wrong image for the current item (since ViewHolders are reused when scrolling). Libraries like Glide handle this for you!

In some cases where you're using Intents to fetch images, you'll get a thumbnail Bitmap in the result Intent (example) while the actual image is accessed via a provided URL. So in those cases, that might be a useful way to display a thumbnail (not in your case, just mentioning it as a good thing to know! Just use Glide etc.)


Your other question is a different one. I'm not sure if File gives you access to a specific reference determined by the filesystem, but even if it did that wouldn't tell you if that file object had changed. You can register a path with a WatchService to watch for changes, but that only works while your app is running obviously.

To look for changes since the app was last run, you'd have to store some state and compare it to the current state. Maybe mapping Path#hashCode to File#lastModified, and looking for changes to that (as well as new files without a path entry, and maybe path entries with no corresponding file). Or you could store checksums for files, using MD5 or something.

You'd probably want to handle this in a repository or something. So your app requests the list of files for a particular directory from the repo, and that handles fetching them from disk, loading the old state, comparing the files and sticking them in a data structure (e.g. a data class that holds the path, updated status etc), updating the stored state, and firing off the data to the requester.

If you want to know more about the repository pattern, have a look at this guide: Data layer. The idea is your list view requests data for a particular directory, puts in a request from a repo component, and gets the data delivered later (usually getting a Flow that's handled in a coroutine). Accessing the disk is quite heavy, which is why it needs to be done concurrently (Glide takes care of this for you, which is why it's nice, but it's only for loading images!)

huangapple
  • 本文由 发表于 2023年5月6日 22:46:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/76189505.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定