关于在适配器中延迟加载位图的共识(重点是 Bitmap.recycle())
我看到了大量的建议,但没有一个(我发现)考虑到所有因素,这些因素是:
- 异步下载,无重复(下载器和位图),并取消下载/分配不会发生的图像 无论如何不再需要
- 一个适配器可以拥有同一个 ID 的多个视图(对 getView(0) 的调用非常频繁)
- 无法保证视图不会丢失而不是回收(考虑 List/GridView 调整大小或按文本过滤)
- 视图和数据/逻辑的分离(尽可能)
- 不为每次下载启动单独的线程(UI 明显变慢)。使用队列/堆栈(LinkedBlockingQueue?)和线程池,或者 诸如此类......但如果活动被破坏则需要结束。
- 清除距离列表/网格中当前位置足够远的位图,最好仅在需要内存时
- 对每个要丢弃的位图调用 recycle()。
- 外部存储器可能不可用(始终或始终),如果使用,应尽快清除(仅清除此处下载的图像)。 还要考虑 Android 的 Activity 销毁/重新创建。
- 数据被更改:条目已删除(在列表中选择、删除按钮、立即刷新)并添加到后台线程(列表 按需刷新)。应保留已下载的位图,如 只要它们链接的条目仍然存在。
- (可选)不依赖于notifyDataSetChanged(据我所知,它会刷新所有可见的、可能非常复杂的列表项) 更新单个 ImageView
- setTextFilterEnabled(true)(如 ArrayAdapter 中所示。其 Filterable 的实现替换了其他 Adapter 可见的数据数组 方法,因此更改视图的索引,因此它们不能 用作链接到位图的 ID)。
- 可在 ExpandableList 中使用(影响缩略图的显示顺序)
如果已回答此问题,请原谅我。我已经搜索了几个月,但没有找到解决方案。
这些要求对我来说似乎很合理,但每一个都增加了一个维度的难度,尤其是 Bitmap.recycle,它需要在运行期间和 Activity 销毁时调用(注意 onDestroy,甚至 onStop 可能不会被调用)。
这也排除了对软引用的依赖,软引用本来可以解决其他一些问题。
是的,这是必要的,否则即使在尝试捕获中进行任意数量的 gc、睡眠(20 秒,甚至)、yield 和巨大的数组分配(以强制控制低内存情况)后,我也会遇到 OutOfMemoryError。
搜索“OutOfMemoryError:位图大小超出 VM 预算”或“android 位图回收”。
是的,我正在对位图进行重新采样。
I see a truckload of suggestions for this, but none (that I've found) take all factors into account, the factors being:
- Asynchronous downloading, without duplication (of downloaders and Bitmaps), with canceling downloads/assigning of images that would no
longer be needed anyway- An adapter can have multiple Views for the same ID (calls to getView(0) are very frequent)
- There is no guarantee that a view will not be lost instead of recycled (consider List/GridView resizing or filtering by text)
- A separation of views and data/logic (as much as possible)
- NOT starting a separate Thread for each download (visible slowdown of UI). Use a queue/stack (LinkedBlockingQueue?) and thread pool, or
somesuch.... but need to end that if the Activity is destroyed.- Purging Bitmaps sufficiently distant from the current position in the list/grid, preferably only when memory is needed
- Calling recycle() on every Bitmap that is to be discarded.
- External memory may not be available (at all or all the time), and, if used, should be cleared (of ONLY the images downloaded here) asap.
Also consider Activity destruction/recreation by Android.- Data being changed: entries removed (select in list, button to remove, immediate refresh) and added in a background Thread (list
refreshed on demand). Already downloaded Bitmaps should be kept, as
long as the entries they're linked to still exist.- (optional) do not rely on notifyDataSetChanged (which, afaik, refreshes all visible, potentially very complex, list items) for
updating a single ImageView- setTextFilterEnabled(true) (as in ArrayAdapter. Its implementation of Filterable replaces the data array visible to the other Adapter
methods, therefore changing indexes of the views, so they cannot be
used as IDs to link to the Bitmaps).- Usable in ExpandableList (affects the order the thumbnails are shown in)
Please forgive me if this had been answered. I've searched for months, and not found a solution.
The requirements seem reasonable to me, but each one adds a dimension of difficulty, especially Bitmap.recycle, which needs to be called during operation and on Activity destruction (note that onDestroy, even onStop might not be called).
This also precludes relying on SoftReferences, which could have taken care of some of the other points.
Yes, it is necessary, or I get OutOfMemoryError even after any number of gc, sleep (20s, even), yield and huge array allocations in a try-catch (to force a controlled low memory situation).
Search for "OutOfMemoryError: bitmap size exceeds VM budget" or "android bitmap recycle".
Yes, I am resampling the Bitmaps.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论