In the development of the application, often involves a large number of images loading and high-precision loading of images, both of which will lead to application Oom (OutOfMemory) problems occur, reasonable picture loading and image memory management is a must solve the problem, the following will provide a more complete technical solution To solve the two problems.
First, we have to make clear why oom (OutOfMemory) problem occurs because the problem with Oom is that the system memory used in the app is running out of the maximum available memory for the current app. Now, let's estimate the number of images loaded in a high-end cell phone that will cause Oom: Assuming that the system allocates the maximum available memory for the app to 32M, loading a picture of 512*512 resolution takes up 2M of memory space, so that if you load 16 images in the app, Oom will appear. In fact, when loading 10 images above, it is very easy to cause oom, because the app will still occupy memory in the run. (PS: Image memory Calculation: Android bitmap default load using argb_8888, each pixel will occupy 4byte, because each pixel has two Chanel, so a 512*512 picture, no matter what format, loading into memory are occupied 512* 512*4*2=2MB, so, Android pictures take up memory size, only with the image resolution (pixels) and load using the color mode related)
To solve the problem of oom, optimize from two aspects: 1. Load Resources reasonably 2. Rational Recovery of resources
Load Resources reasonably
Reasonable load of resources, both if the display image of the ImageView only 128*96 pixel size, this time a picture of 1024x768 completely loaded into memory, it is obviously wrong behavior. This time, you need to load the image to compress the load, is to load resources reasonably.
Below, to carry on the compression explanation of the picture, set the value of Insamplesize in the bitmapfactory.options to achieve equal proportional compression. For example, we have a picture of 2048*1536 pixels, set the value of Insamplesize to 4, you can compress this image into 512*384 pixels. Originally load this picture needs to occupy 26M of memory, compress only then need to occupy 1.5M. The following method calculates the appropriate insamplesize value according to the width and height of the incoming:
public static int calculateinsamplesize (bitmapfactory.options options,int reqwidth, int reqheight) {//the height and width of the source picture final int height = options.outheight;final int width = Options.outwidth;int insamplesize = 1;if (height > reqheight | | width > Reqwidth) {//calculates the ratio of the actual width height to the target width to the final int heightratio = Math.Round (float) height/(float) reqheight); final int Widthra Tio = Math.Round (float) width/(float) reqwidth),///select width and high school minimum ratio as the insamplesize value, so that the final picture width and height//must be greater than or equal to the target width and height. Insamplesize = HeightRatio < WidthRatio? Heightratio:widthratio;} return insamplesize;}
After calculating the appropriate scaling, proceed to the actual compression of the picture:
public static Bitmap Decodesampledbitmapfromresource (Resources res, int resId, int reqwidth, int reqheight) {//First Parse Set Injustdecodebounds to True to get the picture size final bitmapfactory.options Options = new Bitmapfactory.options (); Options.injustdecodebounds = true; Bitmapfactory.decoderesource (res, resId, options); Call the method defined above to calculate the Insamplesize value options.insamplesize = calculateinsamplesize (options, Reqwidth, reqheight); Use the obtained Insamplesize value to parse the picture again options.injustdecodebounds = false; Return Bitmapfactory.decoderesource (res, resId, options);}
Through the above two steps, you can achieve a reasonable load of picture resources.
Rational Recovery of resources
Reasonable recovery of resources, not only the image resources loaded in memory reasonable recovery, to avoid the image resources are no longer used to remain in the memory of the situation occurs. To achieve a reasonable recovery of resources, the core of a class is: LruCache, this class is very suitable for saving image memory, its main algorithm principle is to use the most recently used objects with strong references in the Linkedhashmap, And remove the least recently used object from memory before the cached value reaches its preset value.
Here are the specific ways to use it:
Private lrucache<string, bitmap> Mmemorycache, @Overrideprotected void OnCreate (Bundle savedinstancestate) {// Gets the maximum amount of free memory that is used to exceed this value to cause a OutOfMemory exception. LRUCache passes through the constructor to the cache value, in kilobytes. int maxmemory = (int) (Runtime.getruntime (). MaxMemory ()/1024);//Use 1/8 of the maximum available memory value as the size of the cache. int cacheSize = Maxmemory/8;mmemorycache = new lrucache<string, bitmap> (cacheSize) {@Overrideprotected int sizeOf ( String key, Bitmap Bitmap) {//Override this method to measure the size of each picture, returning the number of pictures by default. return Bitmap.getbytecount ()/1024;}};} public void Addbitmaptomemorycache (String key, Bitmap Bitmap) {if (Getbitmapfrommemcache (key) = = null) {Mmemorycache.put (Key, bitmap);}} Public Bitmap Getbitmapfrommemcache (String key) {return mmemorycache.get (key);}
Just make sure that the entire app's picture resources are used by Addbitmaptomemorycache and Getbitmapfrommemcache toavoid the advent of oom.