7

有人可以告诉我如何为异步制定一个好的机制。下载用于 ListView/GridView 的图像?有很多建议,但每一个都只考虑典型需求的一小部分。

下面我列出了一些我和我的同事无法同时满足的合理因素(要求或需要考虑的事项)。
我不是要求代码(尽管它会受到欢迎),只是一种按照描述管理位图的方法。

  1. 没有重复的下载器或位图
  2. 取消下载/分配不再需要或可能会自动删除的图像(SoftReference 等)
  3. 注意:一个适配器可以有多个相同 ID 的视图(对 getView(0) 的调用非常频繁)
  4. 注意:不能保证视图不会丢失而不是回收(考虑 List/GridView 调整大小或按文本过滤)
  5. 视图和数据/逻辑的分离(尽可能)
  6. 没有为每次下载启动单独的线程(UI 明显变慢)。使用队列/堆栈(BlockingQueue?)和线程池,或类似的......但如果活动停止,则需要结束它。
  7. 清除距离列表/网格中当前位置足够远的位图,最好仅在需要内存时
  8. 在要丢弃的每个位图上调用 recycle()。
  9. 注意:外部存储器可能不可用(完全或始终),如果使用,应尽快清除(仅在此处下载的图像)(考虑 Android 的 Activity 破坏/重新创建)
  10. 注意:可以更改数据:删除条目(多选和删除)和添加(在后台线程中)。应该保留已经下载的位图,只要它们链接的条目仍然存在。
  11. setTextFilterEnabled(true)(如果基于ArrayAdapter的机制,会影响数组索引)
  12. 可在 ExpandableList 中使用(影响缩略图的显示顺序)
  13. (可选)下载位图时,仅刷新相关的 ImageView(列表项可能非常复杂)

请不要张贴个别点的答案。我的问题是,我们越关注某些方面,其他方面就越模糊,类似于海森堡
每一个都增加了一个难度维度,尤其是Bitmap.recycle,需要在运行时和Activity销毁时调用(注意onDestroy,甚至onStop都可能不会调用)。
这也排除了对 SoftReferences 的依赖
这是必要的,否则即使在清空位图后,即使在尝试捕获(强制受控的 OutOfMemory)中进行任意数量的 gc、睡眠(甚至 20 秒)、yield 和巨大的数组分配后,我也会得到 OutOfMemoryError。
我已经重新采样位图。

4

2 回答 2

2

检查这个例子。由于 Google 使用它,我也使用相同的逻辑来避免 OutOfMemory 错误。

http://developer.android.com/resources/samples/XmlAdapters/index.html

基本上这个 ImageDownlaoder 是你的答案(因为它涵盖了你的大部分要求),你也可以在其中实现一些。

http://developer.android.com/resources/samples/XmlAdapters/src/com/example/android/xmladapters/ImageDownloader.html

于 2011-12-14T10:55:18.787 回答
0

最后,我选择完全忽略回收错误。它只是在可管理的过程之上增加了一层不可能的难度。
没有这个负担(只是让适配器等停止显示图像),我创建了一个管理器,Map<String, SoftReference<Bitmap>>用于将下载的位图存储在 URL 下。此外,2-4 个 AsyncTasks(同时使用 doInBackground 和 onProgressUpdate;通过
添加抛出 InterruptedException 的特殊作业来停止)从. deque(为早期 API 复制的 LinkedBlockingDeque 代码)是一个队列,如果不再需要,作业可以离开该队列。地图以作业创建者为键,因此,如果适配器需要下载然后被删除,它会从地图中删除,结果,它的所有作业都会从队列中消失。LinkedBlockingDeque<WeakReference<DownloadingJob>>WeakHashMap<Object, Set<DownloadingJob>>


如果图像已经存在,则作业将同步返回。它还可以包含一组数据,这些数据可以识别它所关注的 AdapterView 中的哪个位置。

缓存也在 SD 卡上(如果可用)在 URLEncoded 名称下完成。(部分清理,从最旧的开始,在应用程序启动时,和/或使用 deleteOnExit()
请求包括“If-Modified-Since”,如果我们有缓存版本,以检查更新。

同样的事情也可以用于 XML 解析, 和大多数其他数据采集。
如果我清理了那个类,我会发布代码。

于 2013-02-05T08:51:25.890 回答