Android memory overflow solution (OOM)

Source: Internet
Author: User
Tags transparent color

As we all know, each Android application has a certain memory limit when running, generally 16 MB or 24 MB (depending on the platform ). Therefore, when developing applications, you must pay special attention to your memory usage. Generally, the most memory-consuming resources are images, audio files, video files, and other multimedia resources; because the Android system parses audio, video, and other resources to play the video, it does not load the entire file into the memory during use, and generally does not experience memory overflow (hereinafter referred to as OOM) so their memory consumption is not discussed in this article. This article focuses on the image memory consumption. If you want to develop an image browser application, such as an app that comes with the Android system Gallery, this problem will become particularly prominent. If you are developing a current shopping client, you may encounter this problem if you are not properly handled.

The OOM scenario is similar to the following situations. However, no matter what the situation is, the solution is consistent.

(1) When the size of an image file reaches 3000*4000;

(2) When a large number of images are loaded in ListView, Gallery, and other controls at a time;

Related Knowledge

1. Color Model

Common color models include RGB, YUV, and CMYK. Most image APIs use RGB models, as does Android. In addition, there is a color model with transparency Alpha in Android, that is, ARGB. More detailed information about the color model is not covered in this article.

2. Digital Coding of color values in computers

Without considering transparency, there are three methods to express the color value of a pixel in the computer:

(1) floating point number encoding: for example, float: (1.0, 0.5, 0.75). Each color component occupies one float field. 1.0 indicates that the value of this component is full red, full green, or full blue;

(2) 24-bit integer encoding: for example, 24-bit: (255,128,196). Each color component occupies 8 digits and the value range is 0-255, 255 indicates that the value of this component is full red, full green, or full blue;

(3) 16-bit integer encoding: for example, 16-bit: (31, 45, 31). Each of the 1st and 3rd color components occupies 5 digits. The value ranges from 0 to 31, 2nd color components make up 6 digits, with a value ranging from 0 to 63;

In Java, float variables occupy 32 bits, int variables occupy 32 bits, and short and char variables both occupy 16 bits, the color of a pixel is encoded in floating-point notation. The memory usage is 96 bytes, that is, 12 bytes. The 24-bit integer notation is used for encoding as long as an int type variable, it occupies 4 bytes (8 characters in height and 24 characters in color). It is encoded in 16-bit integer notation. Only one short type variable occupies 2 bytes; therefore, we can see that using integer notation to encode the color value can greatly save the memory, of course, the color quality will be relatively low. In Android, Bitmap is also encoded in integer format.

In the preceding two integer-encoded representation methods, the order of R, G, and B components can be RGB or BGR, while that of Android is RGB, this article also follows this order. In the 24-bit integer representation method, R, G, and B have eight parts each, and sometimes the industry uses RGB888 to refer to this information. Similarly, in the 16-bit integer representation method, the R, G, and B components are 5, 6, and 5, respectively. This information is referred to as RGB565.

Now we can consider transparent color encoding. In fact, the method is the same as that of transparent encoding: The 24-bit integer encoding RGB model uses int type variables, the idle 8-bit height is used to place the transparency component, where 0 indicates full transparency, and 255 indicates full opacity. In the order of A, R, G, and B, ARGB8888 can be used to summarize this situation. The 16-bit integer RGB model uses the short type variable to adjust the number of each component to four, respectively, then, four digits can be left blank to encode the transparency value. In the order of A, R, G, and B, ARGB4444 can be used to summarize this situation. Recall that the BitmapConfig class of Android contains constants such as ARGB_8888, ARGB_4444, and RGB565. Now we can know what they represent. You can also calculate the memory size of an image. For example, you can use ARGB_8888 encoding to load a 1920*1200 image, it will probably occupy 1920*1200*4/1024/1024 = 8.79MB of memory.

3. Storage Area of Bitmap in memory

In the article of http://www.7dot9.com/2010/08/android-bitmap%E5%86%85%E5%AD%98%E9%99%90%E5%88%B6/, the limitation of Android memory is discussed. The author thinks that Bitmap object points to the Bitmap object on the stack through the reference on the stack, the Bitmap object corresponds to a native image that uses external storage. In fact, it uses byte [] to store the memory space. However, to ensure that the external memory is successfully allocated, you must ensure that the size of the allocated memory cannot exceed the maximum memory value of the current heap, in addition, the external memory is fully considered as part of the current heap in memory management.

4. reference types of Java objects

(1) StrongReference: if an object has a strong reference, the garbage collector will never recycle it. When the memory space is insufficient, the Java Virtual Machine would rather throw an OutOfMemoryError to terminate the program abnormally, and does not recycle strongly referenced objects at will to solve the problem of insufficient memory.

(2) SoftReference if an object only has soft references, the garbage collector will not recycle the object if the memory space is insufficient, the memory of these objects will be recycled. The object can be used by programs as long as the garbage collector does not recycle it.

(3) WeakReference: the difference between a weak reference and a soft reference is that only objects with a weak reference have a shorter life cycle. When the Garbage Collector thread scans the memory area under its jurisdiction, its memory will be recycled no matter whether the current memory space is sufficient or not.

(4) PhantomReference, as its name implies, is a virtual reference. It is different from several other types of references. Virtual Reference does not determine the object lifecycle. If an object only holds a virtual reference, it is the same as no reference and may be recycled by the garbage collector at any time.

Solutions for OOM

The memory limit is a system-level limitation on applications by Android. As an application-layer developer, there is no way to completely eliminate this restriction. However, you can use some reasonable means to avoid this problem. The following are some common methods I have summarized:

(1) cache images to the memory and use soft references to cache the images to the memory, instead of loading the images to the memory every time they are used;

(2) Adjust the image size. If the screen size of the mobile phone is limited, the display area allocated to the image itself will be smaller. Sometimes the image size can be adjusted as appropriate;

(3) Use a low memory usage encoding method. For example, Bitmap. Config. ARGB_4444 saves more memory than Bitmap. Config. ARGB_8888;

(4) reclaim images in a timely manner. If a large number of Bitmap objects are referenced and the application does not need to display all the images at the same time, the temporarily unavailable Bitmap objects can be recycled in a timely manner;

(5) customize heap memory allocation to optimize heap memory allocation for Dalvik virtual machines;

This article mainly demonstrates and analyzes the previous four methods.

Demo Test Description

To illustrate the OOM scenario and solve the OOM problem, I created an Android app-OomDemo for demonstration. The basic situation of this application is described as follows:

(1) The app displays a gallery. This gallery only loads images. The path of the imported image in the gallery adapter is not the image object itself. The adapter dynamically loads the image;

(2)demonstrate that the image used is pre-stored to the cachedirectory of sdcard. the file name is a.jpg, B .jpg... R.jpg, a total of 18;

(3) The image is a jpg image of the specification of 1920*1200. The file size is within the range of 423KB-1.48MB;

(4) running environment: Simulator -- android2.2 Version System -- 480*320 screen size; Moto Defy -- 2.3.4 version CM7 System -- 854*480 screen size;

(5) BASIC program structure:

Demonstration Result and description

1. Demo 1

Firstly, SimpleImageLoader. class assumes this responsibility without any image caching, resizing, or recycling. The code for loading the image is as follows:

@ Override

Public Bitmap loadBitmapImage (String path ){

Return BitmapFactory. decodeFile (path );

}

@ Override

Public Drawable loadDrawableImage (String path ){

Return new BitmapDrawable (path );

}

Demo result: only 1-3 images can be loaded on the simulator, and an OOM error will occur later. No error will occur on Defy. The reason is that the two have different memory limits and Defy runs a third-party ROM, the memory is allocated 40 MB. In addition, each time gallery shows an image, it needs to be parsed to obtain an image. Although there is no error in Defy, when the image volume increases, GC collection is not as effective as time goes, OOM may still occur.

2. Demonstration 2

Add a soft reference cache for image loading. Each time an image gets an image object from the cache, if the cache does not exist, the image will be loaded from Sdcard and added to the cache. At the same time, soft-referenced objects also help GC to recycle them when the memory is insufficient. ImageLoaderWithCache. class is responsible for this responsibility. The key code is as follows:

Private HashMap > MImageCache;

@ Override

Public Bitmap loadBitmapImage (String path ){

If (mImageCache. containsKey (path )){

SoftReference SoftReference = mImageCache. get (path );

Bitmap bitmap = softReference. get ();

If (null! = Bitmap)

Return bitmap;

}

Bitmap bitmap = BitmapFactory. decodeFile (path );

MImageCache. put (path, new SoftReference (Bitmap ));

Return bitmap;

}

@ Override

Public Drawable loadDrawableImage (String path ){

Return new BitmapDrawable (loadBitmapImage (path ));

}

Demo result: on the simulator, one or two images can be loaded without caching, but OOM still occurs. No error occurred in Defy. Because the images used this time are relatively memory-consuming, when GC has not had time to recycle soft reference objects, it has to apply for memory space that exceeds the remaining amount, so it still cannot completely avoid OOM. If you load a large number of small images, such as the 100*100 specification, the soft reference function in the cache may be used. (This assumption can be further tested to prove)

3. Demo 3

To further avoid OOM, in addition to caching, images can be compressed to further reduce memory usage. In most cases, adjusting the image size does not affect the application performance. ImageLoaderWithScale. class is responsible for this responsibility. The code for resizing is as follows:

BitmapFactory. Options options = new BitmapFactory. Options ();

Options. inJustDecodeBounds = true;

BitmapFactory. decodeFile (path, options );

If (options. mCancel | options. outWidth =-1 | options. outHeight =-1 ){

Log. d ("OomDemo", "alert !!!" + String. valueOf (options. mCancel) + "+ options. outWidth + options. outHeight );

Return null;

}

Options. inSampleSize = Util. computeSampleSize (options, 600, (int) (1*1024*1024 ));

Log. d ("OomDemo", "inSampleSize:" + options. inSampleSize );

Options. inJustDecodeBounds = false;

Options. inDither = false;

Options. inPreferredConfig = Bitmap. Config. ARGB_8888;

Bitmap bitmap = BitmapFactory. decodeFile (path, options );

Demonstration Result: In the above Code, the boundary of the image is decoded first, and the image width and height can be obtained without obtaining the Bitmap object (the width and height values are set to options respectively. outWidth and options. ). The parameters of the computeSampleSize method are "BitmapFactory. Options required for image resolution", "minimum width or high value of the adjusted image", and "maximum memory usage of the adjusted image ". In combination with the width and height of the original image, this method can be used to calculate an adjusted proportion, and then adjust the original image and load it into the memory, the memory consumed by the image will not exceed the size specified in advance. In the simulator, when the memory occupied by images is limited to 1*1024*1024, more images can be loaded than those that are not compressed, but OOM will still appear; if the image memory size is limited to 0.5*1024*1024, all images can be loaded completely. Therefore, adjusting the image size can effectively save memory. No error occurs in Defy. The cause is the same as above.

4. Demonstration 4

In some cases, seriously narrowing down the image will still affect the Display Effect of the application. Therefore, it is necessary to display the image with as few as possible. In this case, it is particularly important to manually recycle the image. In the ImageLoaderWithRecyle. class, the image resource recycling method is added:

@ Override

Public void releaseImage (String path ){

If (mImageCache. containsKey (path )){

SoftReference Reference = mImageCache. get (path );

Bitmap bitmap = reference. get ();

If (null! = Bitmap ){

Log. d ("OomDemo", "recyling" + path );

Bitmap. recycle ();

}

MImageCache. remove (path );

}

}

Demonstration Result: The image compression limit is still 1*1024*1024. In the adapter, call the releaseImage method in time to recycle unnecessary images temporarily. In this case, OOM has never been used in the simulator. In general, it can effectively avoid OOM by means of caching, resizing, and recycling.

5. Optimize heap memory allocation for the Dalvik Virtual Machine

For the Android platform, the Dalvik JavaVM used by its hosting layer can be optimized from the current performance, for example, when developing large game or resource-consuming applications, we may consider Manual Interference with GC and use dalvik. system. the setTargetHeapUtilization method provided by the VMRuntime class can improve the processing efficiency of the program heap memory. Of course, we can refer to the open-source project for specific principles. Here we only talk about the usage method: the code is as follows:

Private final static floatTARGET_HEAP_UTILIZATION = 0.75f;

You can call

VMRuntime. getRuntime (). setTargetHeapUtilization (TARGET_HEAP_UTILIZATION );

You can.

6. Customize the memory size required by our application

Private final static int CWJ_HEAP_SIZE = 6*1024*1024;

// Set the minimum heap memory size to 6 MB.

VMRuntime. getRuntime (). setMinimumHeapSize (CWJ_HEAP_SIZE );

Summary

This article introduces some methods to avoid OOM, such as soft reference cache, size adjustment, and recycle. The overall effect is obvious. However, in actual application scenarios, the image application is not as simple as described in this article. Sometimes, image resources may come from the network, in this case, the asynchronous loading method is used to download the image and display it through the callback method. Sometimes the image resources also need to be added with borders, text, and other additional modifications, therefore, you need to process the image after it is loaded.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.