When Android loads a large background image or a large number of images, it often results in memory overflow (out of the memories Error), this article according to my experience in dealing with these issues and other developers experience, the following (some code and text source can not be verified):
plan One, read the picture when the method calls attention, appropriate compression try not to use setimagebitmap or setimageresource or Bitmapfactory.decoderesource to set a large image, because these functions are finished decode, and eventually through the Java layer CreateBitmap to complete, need to consume more memory. Therefore, instead of using the Bitmapfactory.decodestream method First, create a bitmap, and then set it to ImageView source,Decodestream The biggest secret is that it directly calls Jni>>nativedecodeasset () to complete the decode, eliminating the need to use the Java layer's createbitmap, thus saving the Java layer space.
InputStream is = this. getresources (). Openrawresource (R.DRAWABLE.PIC1);
Bitmapfactory.options Options = new bitmapfactory.options ();
Options.injustdecodebounds = false;
Options.insamplesize = 10; Width,hight is set to the original very
Bitmap BTP = bitmapfactory. Decodestream (IS, null, Options);
If the config parameter is added at the time of reading, it can be followed by effectively reducing the loaded memory, thereby effectively blocking the throw out of the "Memories" exception.
/**
* Read pictures of local resources in the most memory-saving way
* @param Context
* @param resId
* @return
*/
Public Static Bitmap Readbitmap (context context, int resId) {
Bitmapfactory.options opt = new bitmapfactory.options ();
Opt.inpreferredconfig = Bitmap.config. rgb_565;
Opt.inpurgeable = true;
Opt.ininputshareable = true;
Get a picture of a resource
InputStream is = Context.getresources (). Openrawresource (ResId);
return Bitmapfactory. Decodestream (IS, null, opt);
}
In addition, Decodestream directly take pictures to read bytecode, not according to the machine's various resolutions to automatically adapt, after using the Decodestream, you need to configure the corresponding image resources in hdpi and mdpi,ldpi. Otherwise the same size (number of pixels) is the same on different resolution machines, and the displayed size is wrong.
scenario Two, in the appropriate time to recover images occupied by the memory usually activity or fragment at Onstop/ondestroy time can release the image resources:
if (ImageView! = null && imageview.getdrawable ()! = null) {
Bitmap Oldbitmap = ((bitmapdrawable) imageview.getdrawable ()). Getbitmap ();
Imageview.setimagedrawable (null);
if (Oldbitmap! = null) {
Oldbitmap.recycle ();
Oldbitmap = null;
}
}
Other code.
System. GC ();
When releasing resources, it is important to note whether the released bitmap or related drawable are referenced by other classes. If the call is normal, the bitmap.isrecycled () method can be used to determine if a tag is being recycled, and if it is being utilized by the UI thread's interface-related code, you need to be especially careful not to reclaim resources that might be used, or you might throw a system exception: e/ AndroidRuntime:java.lang.IllegalArgumentException:Cannot Draw recycled bitmaps and the exception cannot be effectively captured and processed.
scenario three, when unnecessary to avoid the full load of the picture only need to know the picture size of the case, can not fully load the picture into memory. When using bitmapfactory to compress a picture,bitmapfactory.options set injustdecodebounds to True, then use the DecodeFile () and so on, you can calculate the size of the picture in the non-allocated space state. Example:
Bitmapfactory.options opts = new bitmapfactory.options ();
Set Injustdecodebounds to False
Opts.injustdecodebounds = false;
Use the DecodeFile method to get the width and height of the picture
Bitmapfactory. DecodeFile (path, opts);
Print out the width and height of the picture
Log. D ("Example", Opts.outwidth + "," + opts.outheight);
(PS: The principle is actually through the picture's head information to read the basic information of the picture)
scenario Four, the heap memory allocation heap that optimizes the Dalvik virtual machine is the most memory-intensive part of the VM, usually dynamically allocated. The size of the heap is not immutable, and there is usually an allocation mechanism to control its size. For example, the initial heap is 4M large, when 4M space is occupied more than 75%, the redistribution heap is 8M large, when 8M is occupied more than 75%, the allocation heap is 16M large. Upside down, when the 16M heap utilization is less than 30%, the size of the reduction is 8M large. The size of the heap, especially compression, usually involves a copy of the memory, so the size of the change heap has an adverse effect on efficiency. Heap utilization is the utilization of heaps. When the actual utilization deviates from this percentage, the virtual opportunity adjusts the heap memory size in the GC, allowing the actual occupancy rate to converge to a percentage. Using the settargetheaputilization method provided by the Dalvik.system.VMRuntime class can enhance the processing efficiency of the program heap memory.
Private Final Static float Target_heap_utilization = 0.75f;
Can be called when the program is OnCreate
Vmruntime.getruntime (). Settargetheaputilization (target_heap_utilization);
scenario Five, custom heap (heap) memory size for some Android projects, the main impact of the performance bottleneck is Android's own memory management mechanism, the current handset manufacturers are stingy with RAM, for the smoothness of the software, the impact of RAM on performance is very sensitive, In addition to optimizing heap memory allocations for Dalvik virtual machines, we can also enforce our own software's memory size, using the Dalvik.system.VMRuntime class provided by Dalvik to set the minimum heap memory as an example:
Private Final Static int Cwj_heap_size = 6 * 1024 * 1024;
Vmruntime.getruntime (). Setminimumheapsize (Cwj_heap_size); Sets the minimum heap memory size to 6MB.
But the above method still has the problem, the function setminimumheapsize actually only changes the heap the lower limit value, it can prevent too frequently the heap memory allocation, when sets the minimum heap memory size exceeds the upper limit value (Max heap size) still uses the heap the upper limit value, Doesn't work for low memory.
At last, we introduce the memory algorithm of the occupied process. The base class for working with images in Android is bitmap, as the name implies, bitmaps. Memory-intensive algorithms such as: Width*height*config of images. If config is set to argb_8888, then the config above is 4. A 480*320 picture takes up memory that is 480*320*4 byte. The memory footprint of the Android process is 16M by default, because bitmap he holds data in addition to Java, the underlying C + + Skia Graphics library holds a Skbitmap object, so the general picture should not exceed 8M in memory recommended size. This can be adjusted, you can set the parameters when compiling the source code.
Picture--android loading a picture causing memory overflow (out of storage exception)