Recently, in addition to busy project development on the matter, there is to prepare my graduation thesis, there is a short period of time not to write a blog, tonight is rare to summarize, just a little time, so make up a piece, good, nagging words not much to say, directly into the topic. Since the development of Android mobile, presumably is often to deal with memory problems, when it comes to the memory problems encountered in Android development, such as bitmap this kind of memory to eat a little bit improper processing is easy to cause oom, of course, there are many well-known open-source picture loading framework, For example: Imageloader,picasso and so on, these frameworks have been able to solve the oom problem caused by bitmap, although these frameworks can save a lot of developers valuable time, but also encounter a situation, many beginners will simply go to invoke the interface provided by these frameworks , was asked in the framework of some of the implementation of the principle, is basically a blank in the brain. From my point of view, I think if you can master some of the framework of principles, presumably for us to apply the significance of tuning is very significant, today, is mainly to talk about, if there is no picture loading framework, how can we deal with bitmap memory problem?
When it comes to bitmap, we may want to start with some basic knowledge about bitmap memory allocations in Android virtual machines and give the following paragraph on Google's website
The general meaning is that Prior to Android3.0, bitmap's memory allocation was divided into two parts, part of which was allocated in Dalvik's VM heap, while the memory of the pixel data was allocated in the native heap, and Android3.0 's memory was all allocated on the VM heap after bitmap, the difference between the two allocation methods , native heap of memory is not managed by the Dalvik virtual machine, we want to release bitmap memory, we must call recycle method manually, and to the platform after Android 3.0, we can put bitmap memory completely assured to the virtual machine management, We only need to ensure that the bitmap object complies with the garbage collection rules of the GC Root tracing of the virtual machine. OK, basic knowledge of science to this. Here are a few points to talk about how to optimize bitmap memory issues.
1.Bitmap Reference counting method (for the optimization of the platform prior to Android3.0, first demo Code)
Private intMcacherefcount =0;//Cache reference CountersPrivate intMdisplayrefcount =0;//Display reference counter...//The current bitmap is displayed on the UI interface Public void setisdisplayed(Booleanisdisplayed) {synchronized( This) {if(isdisplayed) {mdisplayrefcount++; mhasbeendisplayed =true; }Else{mdisplayrefcount--; }} checkstate ();}//Whether the token is cached Public void setiscached(Booleaniscached) {synchronized( This) {if(iscached) {mcacherefcount++; }Else{mcacherefcount--; }} checkstate ();}//used to detect if bitmap has been recycledPrivate synchronized void CheckState() {if(Mcacherefcount <=0&& Mdisplayrefcount <=0&& mhasbeendisplayed && Hasvalidbitmap ()) {Getbitmap (). Recycle (); }}Private synchronized Boolean Hasvalidbitmap() {Bitmap Bitmap = Getbitmap ();returnBitmap! =NULL&&!bitmap.isrecycled ();}
The above instance code, which uses the method of reference counting (Mdisplayrefcount and Mcacherefcount) to track whether a bitmap is currently displayed or is in the cache. Recycle bitmap When the following conditions are met:
Both Mdisplayrefcount and Mcacherefcount have a reference count of 0.
Bitmap is not NULL, and it has not been recycled.
2. Using the cache, LRUCache and disklrucache combination
About LRUCache and Disklrucache, we certainly will not be unfamiliar (friends who have doubts can go to the API website search LRUCache, and Disklruccache can refer to this Good article: Disklrucache use introduction), For performance and app considerations, we must be thinking of the first time from the network loaded into the picture, the image can be cached in memory and SD card, so that we do not have to go to the network to load the image, in order to control the memory problem very well, You will consider using LRUCache as the storage container for bitmap in memory, and the SD card using Disklrucache to uniformly manage the picture cache on the disk.
combination of 3.SoftReference and Inbitmap parameters
In the 2nd, it is mentioned that LRUCache can be used as a container for storing bitmap, while in LRUCache there is a way to note that entryremoved, according to the documentation, This method is called when the LRUCache container is full of objects that need to be eliminated ( Note that this is just the object being eliminated from the LRUCache container, but it does not mean that the object's memory is immediately reclaimed by the Dalvik virtual machine ), At this point, you can wrap the bitmap using SoftReference in this method, and use a pre-prepared hashset container to hold the bitmap that will be recycled, and someone will ask, what's the point of storing it? The reason why this is stored, It is also necessary to refer to the Inbitmap parameter (which begins at Android3.0, the details of the bitmapfactory.options parameter information in the API), which is mainly provided to us for the bitmap in the multiplexed memory, if this parameter is set and the following conditions are met:
- Bitmap must be variable, that is, the inmutable setting must be ture;
- Android4.4 below the platform, need to ensure that the inbitmap and will be decode to get the size of the bitmap the same;
- Android4.4 and above the platform, only need to meet the size of the inbitmap to decode to get bitmap size specifications can be;
When the above conditions are met, the system will check the memory for reusable bitmap when decoder the image, to avoid the system performance degradation caused by frequent loading of images on SD card, after all, it is more than dozens of times times more efficient to reuse from memory directly than to perform IO operation on SD card. Write too much text, followed by a few sections of the demo code
Set<softreference<bitmap>> Mreusablebitmaps;PrivateLrucache<string, bitmapdrawable> Mmemorycache;//used to put out the bitmap by LRUCache eliminationif(Utils.hashoneycomb ()) {mreusablebitmaps = Collections.synchronizedset (NewHashset<softreference<bitmap>> ());} Mmemorycache =NewLrucache<string, bitmapdrawable> (mcacheparams.memcachesize) {//When LRUCache obsolete objects, it is called to reuse bitmap in memory to improve the performance of loading pictures. @Override protected void entryremoved(BooleanEvicted, String key, Bitmapdrawable OldValue, bitmapdrawable newvalue) {if(RecyclingBitmapDrawable.class.isInstance (OldValue)) {(recyclingbitmapdrawable) oldValue). setiscached (false); }Else{if(Utils.hashoneycomb ()) {Mreusablebitmaps.add (NewSoftreference<bitmap> (Oldvalue.getbitmap ())); } } }....}Private Static void addinbitmapoptions(Bitmapfactory.options Options, Imagecache Cache) {//Set inmutable to true,inbitmap one of the conditions in effectOptions.inmutable =true;if(Cache! =NULL) {//try to find bitmap that can be reused in memoryBitmap inbitmap = cache.getbitmapfromreusableset (options);if(Inbitmap! =NULL) {options.inbitmap = Inbitmap; } }}//Gets the bitmap that currently satisfies the reuse condition, returns the bitmap if it exists, returns null if it does not existprotectedBitmapGetbitmapfromreusableset(Bitmapfactory.options Options) {Bitmap Bitmap =NULL;if(Mreusablebitmaps! =NULL&&!mreusablebitmaps.isempty ()) {synchronized(Mreusablebitmaps) {Finaliterator<softreference<bitmap>> Iterator = Mreusablebitmaps.iterator (); BITMAP item; while(Iterator.hasnext ()) {item = Iterator.next (). get ();if(NULL! = Item && item.ismutable ()) {if(Canuseforinbitmap (item, options)) {bitmap = Item; Iterator.remove (); Break; } }Else{Iterator.remove (); } } } }returnBitmap;}//Determine if the conditions for using Inbitmap are metStatic BooleanCanuseforinbitmap (Bitmap candidate, bitmapfactory.options targetoptions) {if(Build.VERSION.SDK_INT >= build.version_codes. KITKAT) {///Android4.4 start, the multiplexed bitmap size specification is greater than or equal to the required decoding specifications to meet the reuse conditions intwidth = targetoptions.outwidth/targetoptions.insamplesize;intHeight = targetoptions.outheight/targetoptions.insamplesize;intByteCount = width * Height * getbytesperpixel (candidate.getconfig ());returnByteCount <= Candidate.getallocationbytecount (); }///Android4.4 must meet the bitmap and requested bitmap size specifications before being reused returnCandidate.getwidth () = = Targetoptions.outwidth && candidate.getheight () = = Targetoptions.outheight && Targetoptions.insamplesize = =1;}
4. Reduce the sampling rate, insamplesize calculation
I believe that we will not be unfamiliar with insamplesize, so here no longer do too much introduction, on the reduction of the sampling rate of insamplesize calculation method, I see the online algorithm has a lot, the following this algorithm should be the best algorithm, It also takes into account the processing of images (e.g. panorama) that are very wide-gap in height.
Public Static int calculateinsamplesize(Bitmapfactory.options Options,intReqwidth,intReqheight) {//Raw height and width of image Final intHeight = options.outheight;Final intwidth = options.outwidth;intInsamplesize =1;if(Height > Reqheight | | width > reqwidth) {Final intHalfheight = height/2;Final intHalfwidth = width/2; while(halfheight/insamplesize) > Reqheight && (halfwidth/insamplesize) > Reqwidth) {Insamplesize *=2; }LongTotalpixels = width/insamplesize * height/insamplesize;Final LongTotalreqpixelscap = reqwidth * Reqheight *2; while(Totalpixels > Totalreqpixelscap) {Insamplesize *=2; Totalpixels/=2; } }returnInsamplesize;
5. Using Decodefiledescriptor to encode pictures (temporarily do not know the principle, welcome Master pointing Maze)
about using Decodefiledescriptor to deal with the picture can save memory this aspect, I write the code time to try, really want to save memory than the other decode method, query the online explanation, not very clear, I saw some of the source code also can not get a good idea, Why use this way can save some of the memory, if there is understand the principle of the master, welcome to answer my doubts .
To this, about bitmap processing of several optimization points have been analyzed, for the time being, perhaps everyone in the development process used to use the framework to load the picture, so do not care about the image memory processing related issues, if you want to know some optimization bitmap memory principle or want to make a good picture loading frame , I hope this article can provide you with a little thought. If the reader finds the article to be wrong, please criticize it in the comments below.
Android performance optimization: Talk about bitmap's memory management and optimization