Three-level caching strategy for images in Android

Source: Internet
Author: User
Tags response code

first, Brief introduction

In today's Android apps. Inevitably, images are used. Let's assume that every time you load a picture, you pull it out of the network again, so it's not only consuming user traffic. And the images are loaded very slowly and the user experience is very bad.

So an app's picture caching strategy is very important.

usually. The caching strategy for images in Android apps takes the "memory-local-network" level three cache policy, first the application visits the network to pull pictures, and then save the loaded pictures in the local SD card and in memory. When the program needs to load the image again, the memory is first inferred if there is a cache. There is a direct pull from memory, otherwise see if there is a cache in the local SD card. The SD card assumes that there is a cache, the picture is pulled from the SD card, or the picture is loaded from the network. Based on this three-level caching mechanism. It allows our application to be loaded with images, effectively avoiding memory overflow.

PS: Of course today, when dealing with 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 Bitmaputil, custom 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 downloads the URL corresponding picture. Let's think of it as a cache. Modeled on the display method in Bitmaputil, my own custom Custombitmaputils also defines this method, which sets the picture to the Ivpic control, based on the incoming URL.

public void display (ImageView ivpic, String url) {}
The tool class that defines the network cache, I use Asynctask to access the network. Download the image in Asynctask's Doinbackground method. Then set the picture to the Ivpic control, Asynctask has three generics, where the first generic is the number of parameters passed by execute when the asynchronous task is run. The second generic is the progress of the update. The third generic is the result of returning the asynchronous task after it has finished running, and here we return a bitmap. The detailed 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 network operation must be in the sub-line Asynchronous task Myasynctask task = new Myasynctask () task.execute (ivpic, URL);} /** * The first generic-the time when the asynchronous task runs. The number of parameters passed through execute; the second generic--update progress. Third generic--results returned after the asynchronous task runs * * @author Zhy * */private class Myasynctask extends Asynctask<object, Void, bitmap> {privat E ImageView ivpic;private String url;//Time-consuming task before run--main thread @overrideprotected void OnPreExecute () {Super.onpreexecute ();} Tasks running in the background @overrideprotected Bitmap doinbackground (Object ... params) {//Run the asynchronous task, pass the URL over ivpic = (ImageView) params[0] ; url = (String) params[1]; Bitmap Bitmap = downloadbitmap (URL);//To ensure that the ImageView control and URL one by one correspond. Set a ImageView for theTag 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 runs-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 it to an in-memory copy of localcacheutils.setbitmap2local (URL, result);//after loading from the network. Save the picture to a local SD card, save in memory a copy of memorycacheutils.setbitmap2memory (URL, result);}}  /** * 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 parameters 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 number must be determined according to the size of the image, 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. At the time of loading the picture. Infer whether the SD card has a picture cache, fake. Load the image directly from the SD card. There are two common methods in a locally cached tool class. Each is to set up a network image to the local SD card and get the picture from the SD card.

When the image is set, it is stored in the form of a key-value pair, and the URL of the image is used as the name of the file. The bitmap of the image is stored as a bit value.

Because the URL contains special characters, it cannot be stored directly as the name of the picture. Therefore, 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 to point to the path. The file name is called Filenamefile filename = new file (file_path);//file is actually a picture, its parent file is a directory, infer if the directory exists, if it does not exist, create a directory file Fileparent = File.getparentfile (); if (!fileparent.exists ()) {//directory does not exist Fileparent.mkdirs ();//Create Directory}// Save the picture to a 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 such as the form of key-value pairs to save. Use URL as key,bitmap as value. However, the default new object in Java is a strongly referenced method. The JVM does not recycle the strong references when it is garbage collected, so if there are too many images loaded, the map will become larger and more easy to get an oom exception. It can also be resolved by soft or weak references before Android2.3. But after Android2.3, Google's official no longer recommend soft references, Google recommends that we use LRUCache.

In the past, we often used an implementation of a very popular memory caching technique, either soft or weak (SoftReference or weakreference).

However, it is no longer recommended to use such a method now. Since the start of Android 2.3 (API level 9). The garbage collector is more inclined to reclaim objects that hold soft or weak references. This makes soft references and weak references no longer reliable.

In addition, Android 3.0 (API level 11). The image's data is stored locally in memory, so it cannot be released in a predictable way. This poses a potential risk for the application's memory overflow and crashes.

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

    • 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 may appear on the screen very quickly?
    • What is the screen size and resolution of your device? An ultra-high-resolution device, such as a Galaxy nexus, is more than a lower-resolution device (such as a Nexus S). More cache space is required when holding the same number of images.
    • The size and size of the picture. There is also how much memory space each image will occupy.
    • How often does the picture get interviewed? Will there be some pictures of the frequency than the other pictures to be higher? Suppose there are, you should probably let some pictures reside in memory. Or use multiple LRUCache objects to distinguish between different groups of pictures.

    • Can you maintain a good balance between quantity and quality? There are times. Store multiple low-pixel images. In the background, it is more effective to load high-resolution images into the threads.
The above is Google's description of the LRUCache, in fact, the use of LRUCache is very simple, and map very similar, just to create a LRUCache object when you need to specify its maximum consent memory, One of the eight points that is generally set to the maximum running memory of the current application is available.

/** * Memory Cache * * @author Zhy * */public class Memorycacheutils {/* * Due to the fact that map is strongly referenced by default, all the references to the map are not recycled 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 consent memory is generally given to each application memory size of Android system (default Android system assigns 16 megabytes of memory to each application) one of the eight points (recommended)// Gets the memory size that the current application is running long mcurrentmemory = Runtime.getruntime (). MaxMemory (); int maxSize = (int) (MCURRENTMEMORY/8);// Set the maximum memory for LruCache LruCache = new lrucache<string, bitmap> (maxSize) {@Overrideprotected int sizeOf (String key, Bitmap value) {//Gets the size of the memory per picture//is calculated by multiplying the pixel point of the width of the picture by the height of the pixel int byteCount = value.getrowbytes () * value.getheight ();// Get 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 B Itmap = Softreference.get ();//Soft references are not recommended for use after Android2.3, Google recommends using lrucache//Lru--least recently use//The least recently used, Control the memory within a certain size. Exceeding this memory size will give priority to releasing the least recently used 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 the level three cache policy is encapsulated. Next, customize our own bitmaputils

/** * Self-defined tool class for loading images, similar to the bitmaputil in Xutils, generally uses bitmaputil in practice. In order to understand the level three cache. * Here the simulation bitmaputil itself defines Custombitmaputil * * @author Zhy * */public class Custombitmaputils {private Bitmap bitmap;private Netcacheutils netcacheutils;private localcacheutils localcacheutils;private memorycacheutils MemoryCacheUtils; Public Custombitmaputils () {netcacheutils = new netcacheutils (); localcacheutils = new Localcacheutils (); Memorycacheutils = new Memorycacheutils ();} /** * Load picture, display the current URL corresponding picture to 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. Network Cache netcacheutils.getbitmapfromnet (ivpic, URL);/* * After getting pictures from the network. Save the picture to the phone SD card, in the image display, the priority to read from the SD card cache, key is the image of the URL of the MD5 value. * 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 run are as follows:

The program runs for the first time. Log printing such as the following



Then cache the picture in the SD card and load the picture from the local


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


OK, until now. Android picture of the three-level caching principle is all introduced, I myself benefited, I hope to help the need for friends. Please click on the link below for download for the source code.

Source code 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.