简体   繁体   中英

How to avoid OutOfMemoryError in Android

I'm working on an app which needs to store many bitmap images in memory. No surprise, that OutOfMemoryError is often caught on some devices, when bitmap collection becomes too big. And I need to avoid this somehow.

Saying briefly, I need a kind of collection which will behave a kind of "add items one by one, until adding next item would cause OutOfMemoryError" , but I'm not experienced enough to find a proper approach. I believe, some sort of weak-reference collection should be implemented.

I like WeakHashMap , but there is one crucial problem with it - I cannot control how items will be discarded. In my app, bitmaps are added in order of priority: the most important bitmaps, that should be stored as long as possible, go first. WeakHashMap , as I understand, doesn't provide such prioritization.

Any working approaches or ideas?

PS This question is not about bitmap optimization. Imagine, there are some big objects instead of bitmaps, that cannot be compressed or optimized. The question is about storing items in memory directly controlling their priority, such that objects with low priority can be GC'd quickly or not added at all .


PPS So far, I discovered two possible solutions:

1) dividing a collection in 2 parts, such that first, more prioritized, will contain items themselves (ie strong references), and second will contain soft references . Control of adding can be processed using Runtime.getRuntime.maxMemory() and .totalMemory() --when totalMemory occupied by the heap exceeds some % of maxMemory, adding new items into collection should be prohibited;

2) using a collection of soft references and track items' finalize() --when it is invoked (ie corresponding object is going to be picked by GC), return this item as a soft reference back to the collection and replace another item--with least priority--by phantom reference. Theoretically, this would give more strict priority control, but I'm not sure how it will behave in practice.

The LruCache class appears to be a good candidate for this.

http://developer.android.com/reference/android/util/LruCache.html

A cache that holds strong references to a limited number of values. Each time a value is accessed, it is moved to the head of a queue. When a value is added to a full cache, the value at the end of that queue is evicted and may become eligible for garbage collection.

This appears to provide the lifetime control you desire. Further, the cache size is in your control, so you can dynamically create a cache that uses a percentage of available memory, ie adjusts automatically to the amount of available memory.

A related article at http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html gives examples of its use, including a backing disk cache for objects that are not stored in RAM.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM