Android image Level Three cache policy (network, local, memory cache) _android

Source: Internet
Author: User
Tags response code

First, Introduction

Now in the Android application, the inevitable use of the picture, if every time the picture is loaded from the network to pull back, this not only very time-consuming user traffic, and the picture load will be very slow, user experience is very bad. So an application of the image caching strategy is very important. In general, the caching strategy for images in an Android application uses a "memory-local-network" level three cache strategy. First, the application access network pull pictures, respectively, the loaded pictures are saved in the local SD card and memory, when the program needs to load the picture, the first to determine whether there is a cache in memory, There is directly from the memory pull, otherwise see whether there is a local SD card cache, SD card if there is a cache, the picture from the SD card pull, otherwise load pictures from the network. This three-level caching mechanism allows our applications to do their best to load images, effectively avoiding memory overruns.

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

Second, the network cache

The network pulls the picture strictly cannot call the cache, essentially is downloads the URL corresponding picture, we here regards it as the cache one kind. Modelled on the display method in Bitmaputil, my own custom Custombitmaputils also defines this method and sets the picture to the Ivpic control based on the URL passed in.

public void display (ImageView ivpic, String URL) {
}

The tool class that defines the network cache, I use Asynctask to access the network, download the picture in the Asynctask Doinbackground method, and then set the picture to the Ivpic control, Asynctask has three generics, One of the first generics is the execution of an asynchronous task, the parameters passed by execute, the second generic is the progress of the update, and the third generic is the result of the return of the asynchronous task execution, where we return a bitmap. The specific download implementation code is as follows:

/** * Network Cache Tool Class * * @author zhy * */public class Netcacheutils {private localcacheutils localcacheutils; private MEMORYC 
Acheutils memorycacheutils; 
Public Netcacheutils () {localcacheutils = new localcacheutils (); memorycacheutils = new Memorycacheutils (); /** * Download pictures from the network * * @param ivpic * @param url/public void getbitmapfromnet (ImageView ivpic, String URL) {//access to the network of the operator Make sure to do in the child thread, using asynchronous tasks to implement Myasynctask task = new Myasynctask (); Task.execute (ivpic, URL); /** * First generics-the parameters passed by execute when the asynchronous task executes, the second generic-update progress, the third generic-the result of the asynchronous task execution * * @author zhy * * * * * * * * * * * * * * * * * * * * * * * Ask extends Asynctask {private ImageView ivpic; private String URL;//time consuming task before execution--main thread @Override protected void onpreexec 
Ute () {super.onpreexecute (); }//Background tasks @Override protected Bitmap doinbackground (Object ... params) {//When performing an asynchronous task, pass the URL over ivpic = (ImageView) par Ams[0]; url = (String) params[1]; 
Bitmap Bitmap = downloadbitmap (URL); To ensure that the ImageView control and URL one by one correspond, ImageView is set to a tag ivpic.settag (URL); Association Ivpic and URL return bitmap; 
//Update Progress--main thread @Override protected void onprogressupdate (void ... values) {super.onprogressupdate (values); 
}//Time consuming task after execution--main thread @Override protected 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 and save it to a copy of localcacheutils.setbitmap2local (URL, result) in memory;
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 Network picture * * @param URL * @return/private Bitmap downloadbitmap (String URL) {HttpURLConnection conn = null; 
try {URL murl = new URL (URL); 
Open httpurlconnection Connection conn = (httpurlconnection) murl.openconnection (); Setting parameter Conn.setconnecttimeout (5000); Conn.setreadtimeout (5000); 
Conn.setrequestmethod ("get"); 
Open connection Conn.connect ();
Get response code INT code = Conn.getresponsecode (); if (code = = 200) {//The corresponding success, get the input stream returned by the network inputstream is = Conn.getinputstrEAM (); 
Image of the input stream after the successful, set the image compression parameters, the picture compression bitmapfactory.options Options = new Bitmapfactory.options ();
Options.insamplesize = 2;
The picture is compressed to the width of the original half, in the development of this parameter needs to be based on the size of the picture display to determine, otherwise may show the abnormal options.inpreferredconfig = Bitmap.Config.RGB_565; This compressed minimum//Bitmap Bitmap = Bitmapfactory.decodestream (IS); 
Bitmap Bitmap = Bitmapfactory.decodestream (IS, null, options);//compressed picture return Bitmap; 
} catch (Exception e) {e.printstacktrace (); 
finally {//Disconnect connection conn.disconnect (); 
return null; } }

Third, local cache

After the picture is loaded from the network, save the picture to the local SD card. When loading the picture, judge if there is a picture cache in the SD card, and if so, load the picture directly from the SD card. There are two common methods in the locally cached tool class, which are to set up a network picture to the local SD card to obtain the picture in the SD card. Set the picture when the form of a key-value pair of storage, the image of the URL as a key, as the name of the file, the image of the bitmap as a bit value to save. Because the URL contains special characters, can not be directly stored as the name of the picture, so the MD5 value of the URL as the name of the file.

/** * Local Cache * * @author zhy * * */public class Localcacheutils {/** * File save path * * public static final String File_path =
Environment. getExternalStorageDirectory (). GetAbsolutePath () + "/cache/pics"; /** * from the local SD card to obtain network pictures, key is the MD5 value of the URL * * @param URL * @return/Public Bitmap getbitmapfromlocal (string url) {try {string F
ilename = Md5encoder.encode (URL);
File File = new file (File_path, fileName); if (file.exists ()) {Bitmap Bitmap = Bitmapfactory.decodestream (new FileInputStream (file); return Bitmap;}}
catch (Exception e) {e.printstacktrace ();} return null; /** * Write network picture to local SD card * * @param URL * @param bitmap/public void setbitmap2local (String url, bitmap bitmap) {try {//text
The name of the piece, String fileName = Md5encoder.encode (URL);
Creates a file stream that points to the path, filename named filename file = new file (file_path, filename);
File is actually a picture, its parent file is a folder, determine if the folder exists, if it does not exist, create a folder file Fileparent = File.getparentfile (); if (!fileparent.exists ()) {//folder does not exist Fileparent.mkdirs ();//Create Folder}//Save picture to local bitmap.compress (ComPressformat.jpeg, new FileOutputStream (file));
catch (Exception e) {e.printstacktrace ();}} }

Four, Memory cache

Memory cache To be honest is to save a collection of pictures in memory, first think of hashmap this form of key value pairs to save, with the URL as key,bitmap as value. In Java, however, this default new object is strongly referenced, and the JVM does not reclaim strong references when it is garbage collected, so if there are too many pictures loaded, the map will become larger and more prone to oom exceptions. Before Android2.3, it can be solved by soft reference or weak reference, but after Android2.3, Google will no longer recommend soft references, Google recommends that we use LRUCache.

In the past, we often used a very popular implementation of memory caching techniques, that is, soft references or weak references (SoftReference or weakreference). But this is no longer recommended because the garbage collector, starting with the Android 2.3 (API Level 9), is more likely to recycle objects that hold soft references or weak references, making soft references and weak references less reliable. In addition, in the Android 3.0 (API level 11), the image data is stored in local memory, so it cannot be released in a predictable way, which has the potential risk of the application's memory overflow and crash.

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

How much memory can your device allocate for each application? The android default is 16M. How many pictures can be displayed on the device screen at most once? How many pictures need to be preloaded because they are likely to be displayed on the screen soon? What is the screen size and resolution of your device, respectively? An ultra-high resolution device (such as the Galaxy Nexus) requires more cache space than a lower-resolution device (such as Nexus S) to hold the same number of images. The size and size of the picture, and how much memory space each picture occupies. How often are the pictures accessed? Will there be some pictures that are more frequently accessed than others? If so, you might want to have some images reside in memory, or use multiple LRUCache objects to distinguish pictures from different groups. Can you maintain a good balance between quantity and quality? Sometimes it is more efficient to store multiple images with low pixels and to Chengga in the background to pick up images with high pixel loads. The above is Google's description of the LRUCache, in fact, the use of LRUCache is very simple, and map very similar, 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 can.

/** * Memory Cache * * @author zhy * */public class Memorycacheutils {* * * because map defaults to strong references, all references to the map are not recycled when the JVM is garbage collected///privat
E hashmap<string, bitmap= "" > Map = new hashmap<string, bitmap= "" > (); Examples of soft references, in the case of insufficient memory, the garbage collector will give priority to recycling//private hashmap<string, bitmap= "" >> Msoftreferencemap = new//hashmap<
String, bitmap= "" >> ();
LruCache private lrucache<string, bitmap= "" > LruCache; Public Memorycacheutils () {//LRUCache maximum allowable memory for the Android system for each application memory size (the default Android system for each application allocated 16 megabytes) of one-eighth (recommended)//
Gets the memory size of the current application running long mcurrentmemory = Runtime.getruntime (). MaxMemory ();
int maxSize = (int) (MCURRENTMEMORY/8);  Set maximum memory for lruCache = LruCache = new lrucache<string, bitmap= "" > (maxSize) {@Override protected int sizeOf (string key, Bitmap value) {//Get the size of each picture's memory//The calculation method is: The picture display width pixel point times the height pixel point int byteCount = Value.getrowbytes () * value.getheight ();//
Gets the picture occupied 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 references are deprecated after Android2.3, and Google recommends using LRUCache//Lru--least recently use//least recently, to control the memory in a certain size, exceeding this memory size,
will give priority to releasing the least recently used stuff Bitmap Bitmap = lrucache.get (URL);
return bitmap; /** * Save picture in memory * * @param URL * @param bitmap/public void setbitmap2memory (String url, bitmap bitmap) {//To set in memory, K
Ey,value form, first thought of HashMap//map.put (URL, bitmap);
Save soft references to map//softreference<bitmap> msoftreference = new//softreference<bitmap> (bitmap);
Msoftreferencemap.put (URL, msoftreference);
Lrucache.put (URL, bitmap); }}</bitmap></bitmap></bitmap></string,></string,></string,></string, ></string,></string,>

OK. Now that the level three cache policy is encapsulated, then customize our own bitmaputils

/** * Custom Loading pictures of the tool class, similar to the xutils in the Bitmaputil, in practical use, the general use of bitmaputil, in order to understand the level three cache, * here to simulate the Bitmaputil custom Custombitmaputil * * @ Author Zhy * * */public class Custombitmaputils {private Bitmap Bitmap; private netcacheutils netcacheutils; private Loca
Lcacheutils localcacheutils;
Private Memorycacheutils memorycacheutils; Public Custombitmaputils () {netcacheutils = new netcacheutils (); localcacheutils = new Localcacheutils (); Memorycacheuti
ls = new memorycacheutils ();  /** * Loads the picture, displays the picture of the current URL to the ivpic control * * @param ivpic * ImageView control * @param URL * Image address/public void display (ImageView ivpic, String URL) {//Set default display Picture Ivpic.setimageresource (r.drawable.ic_launcher);//1, memory cache bitmap = Memorycacheutils.get
Bitmapfrommemory (URL);
if (bitmap!= null) {Ivpic.setimagebitmap (bitmap);
SYSTEM.OUT.PRINTLN ("Load pictures from memory cache");
Return
}//2, Local Disk cache bitmap = localcacheutils.getbitmapfromlocal (URL);
if (bitmap!= null) {Ivpic.setimagebitmap (bitmap);
System.out.println ("Picture loaded from local SD card"); Memorycacheutils.setbitmap2Memory (URL, bitmap);//Save picture to memory return;
}//3, Network Cache netcacheutils.getbitmapfromnet (ivpic, URL); * * from the network to obtain pictures, the picture is saved to the phone SD card, in the picture display, priority from the SD card read cache, key is the image of the URL of the MD5 value, * value is saved picture bitmap/}}

Load network pictures using ListView in Mainactivity

/** * Android Three Cache-Network cache-local Cache-Memory Cache * * @author zhy * */public class Mainactivity extends activity {private ListView L
Ist
Private 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", Base_ur L + "/5.jpg", Base_url + "/6.jpg", Base_url + "/7.jpg", Base_url + "/8.jpg", Base_url + "/9.jpg", Base_url + "/10.jpg", BA Se_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 _url + "/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 "};
@Override protected void OnCreate (Bundle savedinstancestate) {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 () {@Override public void OnClick (View v) {Myadapter adapter = new M
Yadapter ();
List.setadapter (adapter);
}
}); Class Myadapter extends Baseadapter {@Override public int getcount () {return urls.length;} @Override public String ge TItem (int position) {return urls[position]:} @Override public long getitemid (int position) {return position;} @Overrid E public View getview (int position, View Convertview, ViewGroup parent) {Viewholder holder; if (Convertview = null) {Co
Nvertview = 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 program runs for the first time and the log prints as follows

Then cache the picture in the SD card and load the picture locally


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


OK, so far, Android image of the three-level caching principle is introduced, I have benefited from myself, I hope to be able to help the needs of friends. Need the source code, please click the link below to download.

Related Article

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.