Could someone tell me how to make a good mechanism for async. download of images for use in a ListView/GridView? There are many suggestions, but each only considers a small subset of the typical requirements.
Below I've listed some reasonable factors (requirements or things to take into account) that I, and my collegues, are unable to satisfy at once.
I am not asking for code (though it would be welcome), just an approach that manages the Bitmaps as described.
- No duplication of downloaders or Bitmaps
- Canceling downloads/assigning of images that would no longer be needed, or are likely to be automatically removed (SoftReference, etc)
- Note: an adapter can have multiple Views for the same ID (calls to getView(0) are very frequent)
- Note: 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 (BlockingQueue?) and thread pool, or somesuch.... but need to end that if the Activity is stopped.
- 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.
- Note: 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 (consider Activity destruction/recreation by Android)
- Note: Data can be changed: entries removed (multi-selection & delete) and added (in a background Thread). Already downloaded Bitmaps should be kept, as long as the entries they're linked to still exist.
- setTextFilterEnabled(true) (if based on ArrayAdapter's mechanism, will affect array indexes)
- Usable in ExpandableList (affects the order the thumbnails are shown in)
- (optional) when a Bitmap is downloaded, refresh ONLY the relevant ImageView (the list items may be very complex)
Please do not post answers for individual points. My problem is that that the more we focus on some aspects, the fuzzier others become, Heisenberg-like.
Each 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.
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 OutOfMemory) after nulling a Bitmap.
I am resampling the Bitmaps already.
entryRemoved
method, where you could callrecycle()
if you overrodesizeOf
to return 4*width*height... except, while it helps, it does not SOLVE the problem. I can guess there might be 10MB non-heap (API<=10) memory for bitmaps available, but, even if there had been, there might not, by the time I fill the cache. OOM. – Jorgensen