Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Asynchronous download of Bitmaps in an Adapter, with emphasis on Bitmap.recycle()

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.

  1. No duplication of downloaders or Bitmaps
  2. Canceling downloads/assigning of images that would no longer be needed, or are likely to be automatically removed (SoftReference, etc)
  3. Note: an adapter can have multiple Views for the same ID (calls to getView(0) are very frequent)
  4. Note: there is no guarantee that a view will not be lost instead of recycled (consider List/GridView resizing or filtering by text)
  5. A separation of views and data/logic (as much as possible)
  6. 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.
  7. Purging Bitmaps sufficiently distant from the current position in the list/grid, preferably only when memory is needed
  8. Calling recycle() on every Bitmap that is to be discarded.
  9. 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)
  10. 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.
  11. setTextFilterEnabled(true) (if based on ArrayAdapter's mechanism, will affect array indexes)
  12. Usable in ExpandableList (affects the order the thumbnails are shown in)
  13. (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.

like image 741
kaay Avatar asked Nov 23 '11 10:11

kaay


1 Answers

Check this example. As Its is used by Google and I am also using the same logic to avoid OutOfMemory Error.

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

Basically this ImageDownlaoder is your answer ( As It cover most of your requirements) some you can also implement in that.

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

like image 83
Arslan Anwar Avatar answered Oct 05 '22 02:10

Arslan Anwar