When we are working on a project, we need to consider the size of the image and the memory size when we encounter an image display. The reason is that the size allocated to Bitmap by Android is only 8 Mb, think about taking a photo on a mobile phone. A normal photo may not take more than 1 MB. Therefore, android has to consider memory exceptions caused by an excessively large image.
At that time, the image was simply cached locally and then compressed. However, it seems that there is no good solution to this problem, but it only reduces the chance of occurrence.
Here, I will reorganize the solutions provided by my predecessors so that they can be used in the future.
1.Perform some processing on memory references. Common examples include soft references, enhanced references, and weak references (refer to this blog:Http://smallwoniu.blog.51cto.com/blog/3911954/1248751)
import java.lang.ref.PhantomReference;import java.lang.ref.Reference;import java.lang.ref.ReferenceQueue;import java.lang.reflect.Field;public class Test { public static boolean isRun = true; public static void main(String[] args) throws Exception { String abc = new String("abc"); System.out.println(abc.getClass() + "@" + abc.hashCode()); final ReferenceQueue referenceQueue = new ReferenceQueue<String>(); new Thread() { public void run() { while (isRun) { Object o = referenceQueue.poll(); if (o != null) { try { Field rereferent = Reference.class .getDeclaredField("referent"); rereferent.setAccessible(true); Object result = rereferent.get(o); System.out.println("gc will collect:" + result.getClass() + "@" + result.hashCode()); } catch (Exception e) { e.printStackTrace(); } } } } }.start(); PhantomReference<String> abcWeakRef = new PhantomReference<String>(abc, referenceQueue); abc = null; Thread.currentThread().sleep(3000); System.gc(); Thread.currentThread().sleep(3000); isRun = false; }}
Result:
class java.lang.String@96354 gc will collect:class java.lang.String@96354
2. process images directly in the memory when loading images in the memory
A. Boundary Compression
@ SuppressWarnings ("unused") private Bitmap copressImage (String imgPath) {File picture = new File (imgPath); Options bitmapFactoryOptions = new BitmapFactory. options (); // The following setting changes the image boundary to adjustable bitmapFactoryOptions. inJustDecodeBounds = true; bitmapFactoryOptions. inSampleSize = 2; int outWidth = bitmapFactoryOptions. outWidth; int outHeight = bitmapFactoryOptions. outHeight; bmap = BitmapFactory. decodeFil E (picture. getAbsolutePath (), bitmapFactoryOptions); float imagew = 150; float imageh = 150; int yRatio = (int) Math. ceil (bitmapFactoryOptions. outHeight/imageh); int xRatio = (int) Math. ceil (bitmapFactoryOptions. outWidth/imagew); if (yRatio> 1 | xRatio> 1) {if (yRatio> xRatio) {bitmapFactoryOptions. inSampleSize = yRatio;} else {bitmapFactoryOptions. inSampleSize = xRatio ;}} bitmapFact OryOptions. inJustDecodeBounds = false; // false --- allowing the caller to query the bitmap without having to allocate the memory for its pixels. bmap = BitmapFactory. decodeFile (picture. getAbsolutePath (), bitmapFactoryOptions); if (bmap! = Null) {// ivwCouponImage. setImageBitmap (bmap); return bmap;} return null ;}
B. When boundary compression is used, soft references are indirectly used to avoid OOM.
/* Some codes in the Custom Adapter */public View getView (int position, View convertView, ViewGroup parent) {File file = new File (it. get (position); SoftReference <Bitmap> srf = imageCache. get (file. getName (); Bitmap bit = srf. get (); ImageView I = new ImageView (mContext); I. setImageBitmap (bit); I. setScaleType (ImageView. scaleType. FIT_XY); I. setLayoutParams (new Gallery. layoutParams (WindowManager. layoutParams. WRAP_CONTENT, WindowManager. layoutParams. WRAP_CONTENT); return I ;}
However, we all know that after decode is completed, these functions are ultimately completed through the createBitmap on the java layer, and more memory is required. If the image size is large, this method still references OOM exceptions, so further processing is required:
A. method 1
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 10-minute Bitmap btp = BitmapFactory. decodeStream (is, null, options); if (! Bmp. isRecycle () {bmp. recycle () // reclaim the memory occupied by the image system. gc () // remind the system to recycle it in time}
B. method 2
/*** Read images of local resources in the most memory-saving manner **/public static Bitmap readBitMap (Context context, int resId) {BitmapFactory. options opt = new BitmapFactory. options (); opt. inPreferredConfig = Bitmap. config. RGB_565; opt. inPurgeable = true; opt. ininputtransferable = true; // obtain the resource image InputStream is = context. getResources (). openRawResource (resId); return BitmapFactory. decodeStream (is, null, opt );}
C. Garbage collection when appropriate
If (bitmapObject. isRecycled () = false) // if bitmapObject. recycle () is not recycled ();
D. 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.
Private final static floatTARGET_HEAP_UTILIZATION = 0.75f; // you can call VMRuntime. getRuntime (). setTargetHeapUtilization (TARGET_HEAP_UTILIZATION) when the program onCreate;
As to why the above is 0.75, it is because HEAP) is the most memory-occupied part of the VM, which is usually dynamically allocated. The heap size is not static. Usually there is a allocation mechanism to control its size. For example, the initial HEAP size is 4 MB. When the space of 4 MB is occupied by more than 75%, the allocated HEAP size is 8 Mb. When the space of 8 Mb is occupied by more than 75%, the allocated HEAP size is 16 Mb. In turn, when the 16 m heap uses less than 30%, the size of the 16 m heap is reduced to 8 m. Resetting the heap size, especially compression, usually involves copying the memory. Therefore, changing the heap size has a negative impact on the efficiency.
E. Customize the memory size required by our applications
Private final static int CWJ_HEAP_SIZE = 6*1024*1024; // set the minimum heap memory to 6 MB VMRuntime. getRuntime (). setMinimumHeapSize (CWJ_HEAP_SIZE );
The above are my summary of some methods to solve the OOM exception, hoping to help you!
Reference blog: http://blog.sina.com.cn/s/blog_7501670601014dcj.html
This article from the "crazy Snail" blog, please be sure to keep this source http://smallwoniu.blog.51cto.com/3911954/1248875