Three-level caching strategy for images in Android

Source: Internet
Author: User
Tags response code

First, Introduction

Now the Android application, the inevitable will be used to the picture, if each time the picture is loaded from the network to pull back, so that not only consumes the user's traffic, and the picture loading will be very slow, the user experience is not good. So an app's image caching strategy is important. Usually, the image in the Android application cache policy using "memory-local-network" level three cache policy, the first application to access the network pull pictures, respectively, the loaded pictures are saved in the local SD card and memory, when the program once again need to load the picture, the first to determine whether there is a cache in memory, There is a direct pull from memory, otherwise see if there is a cache on the local SD card, if there is a cache in the SD card, the picture is pulled from the SD card, otherwise the picture is loaded from the network. Based on this three-level caching mechanism, our application can be used to load images, effectively avoiding memory overflow.

PS: Of course, now processing network pictures, the General people will choose Xutils in the Bitmaputil, it has been the network cache processing is quite good, very convenient to use-I have been in use. Follow the implementation of the idea of Bitmaputil, customize a picture loading tool, to understand the level three cache strategy, I hope there will be a promotion.

second, the network cache

The network pulls the picture strictly does not call the cache, essentially is the download URL corresponding picture, we here consider it as the cache one kind. Modeled on the display method in Bitmaputil, my own custom Custombitmaputils also defines this method, which, based on the incoming URL, sets the picture to the Ivpic control.

public void display (ImageView ivpic, String url) {}
Defines the network Cache tool class, when accesses the network, I use the asynctask to implement, in the Asynctask Doinbackground method to download the picture, then sets the picture to the Ivpic control, Asynctask has three generics, Where the first generic is the execution of an asynchronous task, the second generic is the progress of the update, and the third generic is the result of the completion of the asynchronous task execution, and we return a bitmap here. The specific download implementation code is as follows:

<pre name= "code" class= "java" >/** * Network Cache Tool Class * * @author Zhy * */public class Netcacheutils {private Localcacheuti LS localcacheutils;private memorycacheutils memorycacheutils;public netcacheutils () {localCacheUtils = new Localcacheutils (); memorycacheutils = new Memorycacheutils ();} /** * Download pictures from the Web * * @param ivpic * @param url */public void getbitmapfromnet (ImageView ivpic, String URL) {//access the network operation must be in the sub-line Myasynctask task = new Myasynctask (), Task.execute (ivpic, URL) with asynchronous tasks;} /** * First generic-the parameters passed by execute when the asynchronous task executes, the second generic-update progress, the third generic-the results returned after the asynchronous task execution * * @author Zhy * */private class Myasynctask Extends Asynctask<object, Void, bitmap> {private ImageView ivpic;private String url;//before time-consuming task execution-- Main thread @overrideprotected void OnPreExecute () {Super.onpreexecute ();} Tasks performed in the background @overrideprotected Bitmap doinbackground (Object ... params) {//When executing an asynchronous task, pass the URL over ivpic = (ImageView) params[0] ; url = (String) params[1]; Bitmap Bitmap = downloadbitmap (URL),//In order to ensure that the ImageView control and URL one by one corresponds to the ImageView set aTag ivpic.settag (URL);//correlation ivpic and Urlreturn bitmap;} Update Progress--main thread @overrideprotected void onprogressupdate (void ... values) {super.onprogressupdate (values);} After the time-consuming task executes-the main thread @overrideprotected void OnPostExecute (Bitmap result) {String Mcurrenturl = (string) ivpic.gettag (); if ( Url.equals (Mcurrenturl)) {Ivpic.setimagebitmap (result); System.out.println ("Get Pictures from the network");//after loading from the network, save the picture to a local SD card, save to memory a copy of the localcacheutils.setbitmap2local (URL, result);// After loading from the network, save the picture to a local SD card and save it to a copy of memorycacheutils.setbitmap2memory (URL, result) in memory;}}  /** * Download Web image * * @param URL * @return */private Bitmap downloadbitmap (String URL) {HttpURLConnection conn = null;try {URL murl = new URL (URL);//Open httpurlconnection Connection conn = (httpurlconnection) murl.openconnection ();// Set parameter Conn.setconnecttimeout (conn.setreadtimeout); Conn.setrequestmethod ("GET");//Open Connection Conn.connect (); /Get the response code int code = Conn.getresponsecode (); if (code = = 200) {///corresponding success, get the input stream returned by the network inputstream is = Conn.getinputstream ();//Picture After the input stream gets successful, set the compression parameters of the picture, compress the pictureBitmapfactory.options Options = new Bitmapfactory.options (); options.insamplesize = 2;//Compresses the width of the picture to half the original, In development, this parameter needs to be determined according to the size of the picture, otherwise it may show abnormal options.inpreferredconfig = bitmap.config.rgb_565;//this compression min//Bitmap Bitmap = Bitmapfactory.decodestream (IS); Bitmap Bitmap = Bitmapfactory.decodestream (IS, null, options);//compressed picture return Bitmap;}} catch (Exception e) {e.printstacktrace ();} finally {//disconnects conn.disconnect ();} return null;}}
</pre><p></p><pre>
third, local cacheafter the pictures are loaded from the network, save the pictures to the local SD card. When loading the image, determine if there is a picture cache in the SD card, and if so, load the image directly from the SD card. There are two common methods in the locally cached tool class, which is to set up a network picture to the local SD card to get the picture on the SD card. Set the picture when the key value of the form of the store, the image URL as a key, as the name of the file, the image of the bitmap as a bit value to save. Since the URL contains special characters and cannot be stored directly as the name of the image, the MD5 value of the URL is used as the name of the file.

/** * Local Cache * * @author Zhy * */public class Localcacheutils {/** * file saved path */public static final String File_path = Envi Ronment.getexternalstoragedirectory (). GetAbsolutePath () + "/cache/pics";/** * Get the network picture from the local SD card, key is the MD5 value of the URL * * @param URL * @return */public Bitmap getbitmapfromlocal (string url) {try {string fileName = Md5encoder.encode (URL); File File = new file (File_path, FileName), if (File.exists ()) {Bitmap Bitmap = bitmapfactory.decodestream (New fileinputstr EAM (file); return bitmap;}} catch (Exception e) {e.printstacktrace ();} return null;} /** * Write network image to local SD card * * @param URL * @param bitmap */public void setbitmap2local (String url, bitmap bitmap) {try {//file name s Tring filename = md5encoder.encode (URL);//create a file stream, point to the path, the file name is called Filenamefile file = new file (file_path, filename);// File is actually a picture, its parent file is a folder, determine if the folder exists, if not, create folder file Fileparent = File.getparentfile (); if (!fileparent.exists ()) {// folder does not exist Fileparent.mkdirs ();//Create folder}//save picture to local bitmap.compress (Compressformat.jpeg, 100,new FILEOUTPUTStream (file));} catch (Exception e) {e.printstacktrace ();}}}

Four, memory cache

Memory cache The white is to keep a collection of pictures in memory, first think of hashmap this kind of key-value pairs to save, with the URL as key,bitmap as value. But the default new object in Java is a strong reference, and the JVM does not recycle strong references when it is garbage collected, so if you load too many pictures, the map will become larger and more prone to oom exceptions. Before Android2.3, can also be resolved by soft reference or weak reference, but after Android2.3, Google no longer recommend soft references, Google recommends that we use the LRUCache.

In the past, we often used an implementation of a very popular memory caching technique, either soft or weak (SoftReference or weakreference). However, this is no longer recommended because, starting with Android 2.3 (API Level 9), the garbage collector is more inclined to reclaim objects holding soft or weak references, which makes soft and weak references less reliable. In addition, in Android 3.0 (API level 11), image data is stored in local memory, so it cannot be released in a predictable way, which poses a potential risk of memory overflow and crash of the application.

To be able to choose a suitable cache size for LRUCache, there are several factors that should be taken into account, such as:

    • How much memory can your device allocate for each application? Android default is 16M.
    • How many pictures can be displayed on the device screen at a time? How many images need to be preloaded, as it is possible to be displayed on the screen soon?
    • What is the screen size and resolution of your device? An ultra-high-resolution device, such as a Galaxy nexus, requires more cache space than a lower-resolution device, such as a Nexus S, when holding the same number of images.
    • The size and size of the picture, and how much memory space each image occupies.
    • How often are the images accessed? Will there be some images that are more frequently accessed than other images? If so, you might want to have some images reside in memory, or use multiple LRUCache objects to distinguish different groups of pictures.
    • Can you maintain a good balance between quantity and quality? In some cases, it is more effective to store multiple low-pixel images, while loads in the background to load high-resolution images.
The above is Google's description of the LRUCache, in fact, the use of LRUCache is very simple, very similar to map, but in the creation of LRUCache objects need to specify its maximum allowable memory, generally set to the current application of the maximum running memory of one-eighth.

/** * Memory Cache * * @author Zhy * */public class Memorycacheutils {/* * Due to the fact that map is strongly referenced by default, all references to the map will not be reclaimed when the JVM is garbage collected *///private Ha shmap<string, bitmap> map = new hashmap<string, bitmap> ();//Soft reference instance, when memory is insufficient, the garbage collector will prioritize recycling//private HASHMAP <string, softreference<bitmap>> msoftreferencemap = new//hashmap<string, SoftReference<Bitmap> > ();//Lrucacheprivate lrucache<string, bitmap> lrucache;public memorycacheutils () {// LRUCache Maximum allowable memory for Android system is generally distributed to each application memory size (default Android system to allocate 16 megabytes of memory per application) of one-eighth (recommended)//Get the current application run memory size long mcurrentmemory = Runtime.getruntime (). MaxMemory (); int maxSize = (int) (MCURRENTMEMORY/8);//set maximum memory LruCache = new LruCache String, bitmap> (maxSize) {@Overrideprotected int sizeOf (string key, Bitmap value) {//Gets the size of the memory per picture// The calculation method is: The picture shows the width of the pixel point multiplied by the height of the pixel dot int byteCount = value.getrowbytes () * value.getheight ();//Get the picture takes up memory size return byteCount;}}; /** * Read from memory Bitmap * * @param URL * @return */public Bitmap getbitmapfrommemory (String URL) {//Bitmap Bitmap = map.get (URL);//Softreference<bitmap> softreference = msoftreferencemap.get (URL);//Bitmap Bitmap = Softreference.get ();//Soft reference is not recommended for use after Android2.3, Google recommends using lrucache//Lru--least recently use//least recently used, Control the memory in a certain size, more than this memory size, will give priority to the least recently used those east bitmap bitmap = lrucache.get (URL); return bitmap;} /** * Save picture in memory * * @param URL * @param bitmap */public void setbitmap2memory (String url, bitmap bitmap) {//To in-memory settings, KEY,V Alue form, first think of hashmap//map.put (URL, bitmap);//Save soft reference to map//softreference<bitmap> msoftreference = new// Softreference<bitmap> (BITMAP);//Msoftreferencemap.put (URL, msoftreference); Lrucache.put (URL, Bitmap);}}
All right. Now that the level three cache policy is encapsulated, then customize our own Bitmaputils

/** * Custom Loading image of the tool class, similar to the Bitmaputil in Xutils, in the actual use, generally used bitmaputil, in order to understand the level three cache, * Here simulation bitmaputil Custom Custombitmaputil * @ Author Zhy * */public class Custombitmaputils {private Bitmap bitmap;private netcacheutils netcacheutils;private LocalCac Heutils localcacheutils;private memorycacheutils memorycacheutils;public custombitmaputils () {netCacheUtils = new Netcacheutils (); localcacheutils = new Localcacheutils (); memorycacheutils = new Memorycacheutils ();} /** * Load picture, display the current URL corresponding to the picture on the ivpic control * * @param ivpic * ImageView control * @param URL * Image address */public Voi D Display (ImageView ivpic, String URL) {//Set the default displayed picture Ivpic.setimageresource (r.drawable.ic_launcher);//1, memory cache bitmap = Memorycacheutils.getbitmapfrommemory (URL); if (bitmap! = null) {Ivpic.setimagebitmap (bitmap); SYSTEM.OUT.PRINTLN ("Load Picture from memory Cache"); return;} 2. Local Disk Cache bitmap = localcacheutils.getbitmapfromlocal (URL); if (bitmap! = null) {Ivpic.setimagebitmap (bitmap); SYSTEM.OUT.PRINTLN ("Images loaded from local SD card"); memorycacheutils.setbitmap2memory(URL, bitmap);//Save the picture to memory return;} 3, the network cache netcacheutils.getbitmapfromnet (ivpic, URL); */* * After getting pictures from the network, save the pictures to the phone SD card, in the image display, the priority to read from the SD card cache, Key is the MD5 value of the URL of the picture, * value is the saved picture bitmap */}}
Load a network picture using a ListView in Mainactivity

/** * Android Level three cache-Network cache-local Cache-Memory Cache * * @author Zhy * */public class Mainactivity extends Activity {private ListView list ;p rivate Button btn;private custombitmaputils utils;private static final String Base_url = "http://192.168.0.148:8080/ Pics ";//Initialize some network pictures string[] urls = {base_url +"/1.jpg ", Base_url +"/2.jpg ", Base_url +"/3.jpg ", Base_url +"/4.jpg ", BAS E_url + "/5.jpg", Base_url + "/6.jpg", Base_url + "/7.jpg", Base_url + "/8.jpg", Base_url + "/9.jpg", Base_url + "/10.jpg", Base_url + "/11.jpg", Base_url + "/12.jpg", Base_url + "/13.jpg", Base_url + "/14.jpg", Base_url + "/15.jpg", BASE_URL + "/1 6.jpg ", Base_url +"/17.jpg ", Base_url +"/18.jpg ", Base_url +"/19.jpg ", Base_url +"/20.jpg ", Base_url +"/21.jpg ", BASE_U RL + "/22.jpg", Base_url + "/23.jpg", Base_url + "/24.jpg", Base_url + "/25.jpg", Base_url + "/26.jpg", Base_url + "/27.jpg" , Base_url + "/28.jpg", Base_url + "/29.jpg", Base_url + "/30.jpg"}; @Overrideprotected void OnCreate (Bundle savedinstances Tate) {Super.oncreate (SavediNstancestate); Setcontentview (r.layout.activity_main); list = (ListView) Findviewbyid (r.id.list); btn = (Button) Findviewbyid (r.id.btn_load); utils = new Custombitmaputils ();//load Network picture Btn.setonclicklistener (new Onclicklistener () {@ overridepublic void OnClick (View v) {Myadapter adapter = new Myadapter (); List.setadapter (adapter);}});} Class Myadapter extends Baseadapter {@Overridepublic int getcount () {return urls.length;} @Overridepublic String getItem (int position) {return urls[position];} @Overridepublic long Getitemid (int position) {return position;}  @Overridepublic view GetView (int position, view Convertview, ViewGroup parent) {Viewholder holder;if (Convertview = = null) {Convertview = view.inflate (mainactivity.this,r.layout.item_list, null); holder = new Viewholder (); holder.ivpic = ( ImageView) Convertview.findviewbyid (R.ID.IV); Convertview.settag (holder);} else {holder = (Viewholder) Convertview.gettag ();} Utils.display (Holder.ivpic, urls[position]); return convertview;} Class Viewholder {ImageviEW ivpic;}}} 
The results of the operation are as follows:

The first time the program runs, the log is printed as follows



The picture is then cached in the SD card and loaded locally from the image


Then cache the picture into memory, load the picture from memory


OK, so far, Android pictures of the three-level caching principle has been introduced, I myself benefited, I hope to help the needs of friends. Please click the link below to download the source code.

SOURCE download


Three-level caching strategy for images in Android

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.