Android – 存储从networking下载的图像

我有一个问题,关于是否(以及如何)我应该存储从networking上加载的图像。 比方说,我从我的Android应用程序调用Web服务。 在这个networking服务中,我得到了一个在networking上的图像的url。 我下载并显示在ListView的列表项左侧的图像。 我的问题是,我应该使用什么方法来存储图像? 我是不是该:

  1. 将它保存到SDCard,检查是否存在ListView创build时(在后续请求),并根据需要重新下载(偶尔更新图像,如果它改变)。
  2. 使用Context.getCacheDir()将其存储在caching中,但由于无法依赖保留在caching中的图像,可能会被迫更频繁地重新下载它。
  3. 总是下载它,从不存储图像。

图像文件本身是相当小的,但我希望有一些用户可能有数十个这样的小图像下载/存储。 哪一个最好,和/或什么是首选的方法?

作为一个侧面的问题,我应该首先加载我的ListView中的所有图像(可能会lockingUI一段时间)或asynchronous加载,但同时显示一个占位符graphics(这可能会更“丑陋”)? 这里的标准是什么?

Solutions Collecting From Web of "Android – 存储从networking下载的图像"

关于在哪里存储:答案取决于正在下载什么和多less。 然后你做出select。

例如:如果你正在下载的东西是临时的,减less数量(减less远程抓取)和大小(内存less),并且是本地的一个活动,那么你应该考虑使用SoftReferences在内存中的图像。 SoftReferences可以导致refuse,但由于项目的数量很小,它应该是负担得起的。

但是,如果要下载的项目数量超过一定的阈值(意味着更多的读取和内存),则应考虑通过caching来降低读取次数以及运行时内存消耗。 在这里,您可以select将它们保存在SD卡上或临时存储器上(应用程序的本地caching目录)。 对于只有在应用程序环境下才具有意义的项目(例如缩略图),用户大多不会在应用程序之外使用它。 所以,你可以将这些东西存储在caching目录中。 使用它们的最好的部分是,你不必清理混乱。 它被自动处理。 这可能会导致重新获取。

但是,如果下载的项目很大,并且可以独立于应用程序的上下文之外,如图片,video,audio剪辑,则SD卡应该是您的select。 您还应该阅读: 处理大型位图以避免在BitmapFactory.decodeStream(..)期间出现OOM错误

请注意,您也可以检查使用数据库是否可以在这里帮助。 看到这个

在ListView中延迟加载项目时的一些注意事项:您应该在后台进行加载,不要阻塞UI线程。您应该考虑在下载项目时显示临时图像。 这在许多本地应用程序中很明显。 有关延迟加载的示例实现, 请参阅此 。 此外,对于大型列表,您可以实现SlowAdapter模式(检查API演示)。 当列表滚动时,它基本上停止下载。

示例可以帮助您的项目:

Romain Guy's Shelves项目使用两级caching,其中他使用内存caching(包含SoftReferences的HashMap)和存储在Sdcard上。 在这里浏览源代码

马克·墨菲(Mark Murphy)写的一些开源库(CWAC)和DroidFu也可以帮助你。

祝你好运!

关于你的“侧面问题” – 我认为加载它们是asynchronous的,尤其是因为你需要考虑networking事务,它可能不仅仅是“lockingUI一段时间”,而是“locking用户界面永久“,以防万一它永远不会加载。

如果你认为这种行为很丑,你可以设置一个计时器(1或2秒),使一些图像有机会加载,如果他们全部加载或计时器已经过期,继续显示UI无论如何与占位符图像,让其余的asynchronous加载。 无论如何,这将是防止永久locking的方法。

至于你的问题的第一部分,我认为这取决于你正在显示的图像的上下文和types。 然而,对于大多数网站资产,我认为#2将是首选的方法,因为您当然不希望在同一个会话中多次下载,但您可能不想永久存储。

关于你的“侧面问题” – 我认为asynchronous加载它们是首选的行为,特别是因为你需要考虑到networking事务,它可能不仅仅是“lockingUI一段时间”,而是“locking用户界面永久“,以防万一它永远不会加载。

为了避免这种情况,如果我们正在通过droid-fu讨论WebImageView ,可以将ImageLoader.java initialize()函数更改为

static int alive=-1; public static synchronized void initialize(Context context) { if (executor == null) { executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(DEFAULT_POOL_SIZE); } else if(alive==executor.getActiveCount()){ executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(DEFAULT_POOL_SIZE); } alive=executor.getActiveCount(); if (imageCache == null) { imageCache = new ImageCacheHope(context, 25, 5); } } 

我写了一个Android图像pipe理器,透明地处理caching(内存和磁盘)。 代码在Github上https://github.com/felipecsl/Android-ImageManager