Android those you don't know bitmap object specific explanation

Source: Internet
Author: User

Reprint please indicate this article from Xiaanming's blog (http://blog.csdn.net/xiaanming/article/details/41084843), please respect others ' hard work results, thank you.

We know that the memory allocated to each application by the Android system is limited, bitmap as a large memory drain. Our management of bitmap is a bit inappropriate and may trigger OutOfMemoryError, and bitmap objects have some differences in different versions of the Android version, so let's introduce these differences today. and provide some of the areas where you need to be aware of using bitmap.

In Android2.3.3 (API 10) and previous version numbers, the bitmap object is stored separately from its pixel data, bitmap objects are stored in the Dalvik heap, and the bitmap object's pixel data is stored in native Memory (local RAM) or derict memory (direct RAM), this makes the release of pixel data stored in native memory unpredictable. We can call the Recycle () method to release the pixel data in the native memory, provided that you are able to clearly determine that bitmap is no longer in use, assuming that you call the Bitmap object Recycle () and then draw the bitmap, it will appear " Canvas:trying to use a recycled bitmap "error. After Android3.0 (API 11), Bitmap's pixel data and bitmap objects are stored together in the Dalvik heap, so we don't have to manually call recycle () to release the Bitmap object, and the release of the memory is given to the garbage collector. Perhaps you ask, why do I still appear outofmemoryerror when I display bitmap object?

I'll mention it by the way before I say this question. Before Android2.2 (API 8), the use of the serial garbage collector, from the name can be seen as a single-threaded collector, where the "single-threaded" means not only to use a CPU or a collection thread to collect garbage, more importantly, when it is garbage collection, All other worker threads must be paused, and after Android2.3 the collector is replaced with a concurrent garbage collector. This means that our garbage collection threads and our worker threads do not affect each other.

After a simple understanding of the garbage collector, let's take a simple example of the problem above. If the system starts a garbage collection thread to collect garbage. And at this point we suddenly produce a large number of bitmap objects, at this time it is possible to produce outofmemoryerror. Because the garbage collector first infers whether an object is still alive (the Java language infers whether the object survives using the root search algorithm GC root tracing). Garbage collection algorithms are then used to recycle garbage, and different garbage collection devices have different recycling algorithms. These are all time-outofmemoryerror when it happens. We need to understand whether this is caused by a memory leak or memory overflow (Leak). Suppose it's a memory leak. We need to use tools such as mat to find out the memory leak code and correct it, assuming there is no leak, in other words, the memory object must still be alive, then we can see if there is enough way to reduce the memory consumption of the object. For example, when we use Bitmap, Should be based on the size of the view using Bitmapfactory.options to calculate the appropriate insimplesize to the bitmap to the corresponding clipping, to reduce the use of memory bitmap, assuming that the above is done or there is outofmemoryerror (This is usually a very rare occurrence). Then we can only make the size of the Dalvik heap larger. In Android 3.1 and later, we were able to add an android with a value equal to "true" in the Androidmanifest.xml application tag: The Largeheap property is used to inform the Dalvik virtual machine application that a larger Java Heap is required. But we are not encouraged to do so.


Manage bitmap on Android 2.3 and below

From the above we know that in Android2.3 and below we recommend using the Recycle () method to free up memory. When we use the ListView or the GridView, when should we call recycle ()? Here we use a reference count, using a variable (dispalyrefcount) to record the bitmap display, assuming that bitmap is plotted on the view Displayrefcount plus one, or minus one, Only when Displayrescount is 0 and bitmap is not empty and bitmap has not called recycle (), we need to bitmap () the Recycle object, so we need to wrap the bitmap object in a class, Code such as the following

Package Com.example.bitmap;import Android.content.res.resources;import Android.graphics.bitmap;import Android.graphics.drawable.bitmapdrawable;public class Recyclebitmapdrawable extends bitmapdrawable {private int    Displayrescount = 0;private Boolean mhasbeendisplayed;    Public Recyclebitmapdrawable (Resources res, Bitmap Bitmap) {super (res, BITMAP); }/** * @param isdisplay */public void setisdisplayed (Boolean isdisplay) {synchronized (this) {if (Isdisplay) {mhasbeendisplayed = True;displayrescount + +;} Else{displayrescount--;}} CheckState ();} /** * Check some states of the picture to infer if you need to call recycle */private synchronized void CheckState () {if (displayrescount <= 0 && MHASB    eendisplayed && Hasvalidbitmap ()) {Getbitmap (). Recycle (); }}/** * Infers if Bitmap is empty and has called recycle () * @return */private synchronized Boolean hasvalidbitmap () {Bitmap Bitmap = Getbitm    AP (); return bitmap! = null &&!bitmap.isrecycled ();}}
In addition to the above recyclebitmapdrawable, we also need a self-defined imageview to control when to show bitmap and when to hide bitmap objects

Package Com.example.bitmap;import Android.content.context;import Android.graphics.drawable.drawable;import Android.graphics.drawable.layerdrawable;import Android.util.attributeset;import Android.widget.ImageView;public Class Recycleimageview extends ImageView {public Recycleimageview (context context) {super (context);} Public Recycleimageview (context context, AttributeSet Attrs) {Super (context, attrs);} Public Recycleimageview (context context, AttributeSet attrs, int defstyle) {Super (context, attrs, Defstyle);} @Overridepublic void setimagedrawable (drawable drawable) {drawable previousdrawable = getdrawable (); Super.setimagedrawable (drawable);//Displays the new Drawablenotifydrawable (drawable, true);//The picture before recycling notifydrawable ( Previousdrawable, false);} @Overrideprotected void Ondetachedfromwindow () {//When view is detached from the form, clear drawablesetimagedrawable (null); Super.ondetachedfromwindow ();} /** * Notify the drawable to show or hide * * @param drawable * @param isdisplayed */public static void Notifydrawable (Drawable drawable, b Oolean IsDisplayed) {if (drawable instanceof recyclebitmapdrawable) {((recyclebitmapdrawable) drawable). setIsDisplayed ( isdisplayed);} else if (drawable instanceof layerdrawable) {layerdrawable layerdrawable = (layerdrawable) drawable;for (int i = 0, z = LA Yerdrawable.getnumberoflayers (); I < Z; i++) {notifydrawable (layerdrawable.getdrawable (i), isdisplayed);}}}}
This custom class is also simpler, overriding the Setimagedrawable () method, in which we first get the image above ImageView, and then notify the drawable displayed in ImageView before the display, Drawable will infer if it is necessary to call recycle (), and when the view is detached from the window, it will callback Ondetachedfromwindow (), in which case the image displayed in ImageView is recycled, with detailed usage

ImageView ImageView = new ImageView (context); Imageview.setimagedrawable (New Recyclebitmapdrawable ( Context.getresource (), bitmap));
Only need to wrap bitmap objects with recyclebitmapdrawable. Then set to ImageView above can, detailed memory release we do not need to tube, is it very convenient? This is the memory in Android2.3 and the following version number management bitmap.




Manage bitmap on Android 3.0 and above

Since bitmap's pixel data is also stored in the Dalvik heap in Android3.0 and above, the management of the memory is given directly to the garbage collector, and we do not need to manually release the memory. And today is mainly the BitmapFactory.Options.inBitmap of this field, if this field is set, we are decoding bitmap. He will reuse the Inbitmap set of bitmap, reduce the allocation and release of memory, improve the performance of the application. Before Android 4.4, however, the bitmap set by BitmapFactory.Options.inBitmap must match the size of the bitmap we need to decode. After Android4.4, BitmapFactory.Options.inBitmap set the bitmap greater than or equal to the size of the bitmap we need to decode is OK, let's first assume a scenario, or use a ListView. GridView to load a lot of pictures. In order to improve the efficiency of the application, we usually do the corresponding memory cache and hard disk cache, here we just say the memory cache, and the memory cache is officially recommended to use LRUCache, note that LRUCache only play the role of cache data, and do not reclaim memory. In general, our code will write this.

Package Com.example.bitmap;import Java.lang.ref.softreference;import Java.util.collections;import Java.util.hashset;import Java.util.iterator;import Java.util.set;import Android.annotation.targetapi;import Android.graphics.bitmap;import Android.graphics.bitmap.config;import Android.graphics.bitmapfactory;import Android.graphics.drawable.bitmapdrawable;import Android.os.build;import Android.os.build.version_codes;import Android.support.v4.util.lrucache;public class Imagecache {private final static int max_memory = 4 * 102 * 1024;private Lru Cache<string, bitmapdrawable> mmemorycache;private set<softreference<bitmap>> mReusableBitmaps; private void init () {if (Hashoneycomb ()) {mreusablebitmaps = Collections.synchronizedset (New hashset<softreference <Bitmap>> ());} Mmemorycache = new lrucache<string, bitmapdrawable> (max_memory) {/** * The callback method when the saved Bitmapdrawable object is removed from the LRUCache */@Overrideprotected void entryremoved (Boolean evicted, String key, BitmapdrawableOldValue, bitmapdrawable newvalue) {if (Hashoneycomb ()) {Mreusablebitmaps.add (New softreference<bitmap> ( Oldvalue.getbitmap ()));}}};} /** * from Mreusablebitmaps to get the Bitmap object that can be set to BitmapFactory.Options.inBitmap above * @param Options * @return */protected Bitmap Getbitmapfromreusableset (bitmapfactory.options Options) {Bitmap Bitmap = null;if (mreusablebitmaps! = NULL &&!) Mreusablebitmaps.isempty ()) {synchronized (mreusablebitmaps) {final iterator<softreference<bitmap>> iterator = Mreusablebitmaps.iterator (); Bitmap Item;while (Iterator.hasnext ()) {item = Iterator.next (). get (); if (null! = Item && item.ismutable ()) {if (ca Nuseforinbitmap (item, Options)) {bitmap = Item;iterator.remove (); break;}} else {iterator.remove ();}}}} return bitmap;} /** * Infer if the bitmap can be set to BITMAPFACTORY.OPTIONS.INBITMAP * * @param candidate * @param targetoptions * @return */@TargetApi (V Ersion_codes. KITKAT) public static Boolean Canuseforinbitmap (Bitmap candidate,bitmapfactory.options targetoptioNS) {//After Anroid4.4, if you want to use Inbitmap, only the bitmap needed to decode is smaller than the Inbitmap setting. There is no limit to insamplesize//if (Build.VERSION.SDK_INT >= build.version_codes. KITKAT) {int width = targetoptions.outwidth/targetoptions.insamplesize;int height = targetoptions.outheight/targetopt Ions.insamplesize;int byteCount = width * height* getbytesperpixel (Candidate.getconfig ()); return ByteCount <= Candidate.getallocationbytecount ();} Before android//4.4, the false idea of using Inbitmap, the decoded bitmap must be equal to the width and height of the Inbitmap setting. And Insamplesize is 1return candidate.getwidth () = = targetoptions.outwidth&& Candidate.getheight () = = targetoptions.outheight&& targetoptions.insamplesize = = 1;} /** * Gets the number of bytes consumed per pixel * * @param config * @return */public static int getbytesperpixel (config config) {if (config = = Con Fig. argb_8888) {return 4;} else if (config = = config.rgb_565) {return 2;} else if (config = = config.argb_4444) {return 2;} els e if (config = = config.alpha_8) {return 1;} return 1;} @TargetApi (version_codes. Honeycomb) public static Boolean Hashoneycomb () {return Build.VERSION.SDK_INT >= build.version_codes. Honeycomb;}}
The above is just some example code that saves a weak reference to the Bitmapdrawable object removed from LRUCache in a set. The bitmap object satisfying the BitmapFactory.Options.inBitmap condition is then obtained from the set to improve the decoding bitmap performance. Use such as the following

public static Bitmap decodesampledbitmapfromfile (String filename,        int reqwidth, int reqheight) {    final Bitmapfactory.options Options = new Bitmapfactory.options ();    ...    Bitmapfactory.decodefile (filename, options);    ...    If we ' re running on honeycomb or newer, try to use Inbitmap.    if (Imagecache.hashoneycomb ()) {     options.inmutable = true;        if (cache! = null) {            Bitmap inbitmap = cache.getbitmapfromreusableset (options);            if (inbitmap! = null) {                options.inbitmap = Inbitmap;}}    }    ...    return bitmapfactory.decodefile (filename, options);}

Do you have a better understanding of the bitmap object through this article, and when the application loads a large number of bitmap objects, suppose you do the above. I believe that the probability of an application occurring outofmemoryerror is very small. and performance will be improved a certain amount. I often see some students in the evaluation of a picture loading frame good time. More one-sided to use the process of their own whether the occurrence of outofmemoryerror to the conclusion. Of course often sex happens outofmemoryerror you should check your code for problems first. Generally some of the more mature framework is not a very serious problem, after all, it has been a lot of testing before it is well-known, today's commentary to here, the students have doubts can leave a message below.




Android those you don't know bitmap object specific explanation

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.