Cache Disklrucache on physical storage media for Android level two cache
Android Disklrucache belongs to the physical nature of the cache, compared to the LRUCache cache, then Disklrucache belongs to the last level of the Android level two cache. Usually the Android cache is divided into two levels, the first level is the memory cache, and the second level is the physical cache or Disklrucache. As the name implies, Disklrucache is caching data to Android physical media such as external memory cards, internal memory cards.
As for the LRUCache cache, memory cache, I have written a series of articles before, see Appendix 2, 3 for details. This article describes the cache policy for Android hardware: Disklrucache.
Disklrucache's Android Google official implementation code link:
Disklrucache.java Android Google official source code implementation link: https://android.googlesource.com/platform/libcore/+/jb-mr2-release/luni/ Src/main/java/libcore/io/disklrucache.java
In fact, due to the transparent disclosure of Disklrucache implementation principles and processes, there are a number of third-party implementations, on GitHub there is a more popular Disklrucache open source implementation version, its Project home: Https://github.com/JakeWharton /disklrucache
This article explains the Disklrucache Open Source Library based on the Jakewharton implementation. Using Jakewharton implementation of the Disklrucache, you need to first download the code on GitHub, download, directly copied to your own project code in the Java directory as your own source code directly to use.
(1) Initialization of the Disklrucache.
public static Disklrucache open (File directory, int appversion, int valuecount, long maxSize);
Disklrucache before use, you first need to create a Disklrucache instance from a static method open.
A directory of cache directories, directory directories can be used by the Android system to provide the default cache directory, you can also specify an obvious directory.
Disklrucache in open cache directory, if the front and back appversion different then ecstasy cache.
Valuecount is similar to specifying the length of an array, usually 1, which is 1, then it is newoutputstream (0) at the back of the write cache Newoutputstream, because it resembles an array subscript. An array of length 1, then there is only one element in the array and the subscript for that element is 0. Similarly, reading is also getInputStream (0).
MaxSize meaning simple, specify the size of the Disklrucache cache, you can not let Disklrucache unlimited cache it. So it is generally necessary to give Disklrucache a proper cache size and limit, which is generally * * * 1024,10mb.
I write an example of initialization:
private void Makedisklrucache () { try { File Cachedir = Getdiskcachedir (this, UNIQUENAME); if (!cachedir.exists ()) { log.d (TAG, "cache directory does not exist, create ..."); Cachedir.mkdirs (); } else log.d (TAG, "the cache directory already exists and does not need to be created."); The second parameter I choose the version of the app code. Disklrucache if the second parameter version is found to be different then destroy the cache //third parameter is 1, in the write cache stream, Newoutputstream (0), 0 is the index, like the array subscript Mdisklrucache = Disklrucache.open (Cachedir, Getversioncode (this), 1, disk_cache_max_size); } catch (Exception e) { e.printstacktrace (); } }
(2) The general process of writing the cache toward Disklrucache.
The Disklrucache cache is a <K,V> structure. Cache writes Disklrucache, First to obtain a disklrucache.editor from the Disklrucache, with the Disklrucache.editor Editor to pass the parameter key in, and then get a outputstream, get this outputstream, you can put DISKL Rucache as an output stream that receives data to write data inside. Don't forget commit when you finish writing. A code snippet for Disklrucache write cache:
Writes a byte byte to the cache Disklrucache private void Writetodisklrucache (String URL, byte[] buf) throws Exception { log.d ( TAG, URL + ": Start write Cache ..."); Disklrucache cache requires a key, I first convert the URL into a MD5 string, //And then use the MD5 string as the key key string key=urltokey (URL); Disklrucache.editor Editor = Mdisklrucache.edit (key); OutputStream os = editor.newoutputstream (0); Os.write (BUF); Os.flush (); Editor.commit (); Mdisklrucache.flush (); LOG.D (TAG, url + ": Write Cache complete.");
(3) The general process of reading the cache from Disklrucache.
Read directly from Disklrucache with the key key in the previous write cache: Disklrucache.get (key), Get a snapshot of disklrucache.snapshot, if this disklrucache.snapshot is null, then there is no cache, if any, then the cache is already cached and then an input stream is created from Disklrucache.snapshot to restore the cached data 。 Read the cached code:
Read cache from Disklrucache private Bitmap readbitmapfromdisklrucache (String url) { disklrucache.snapshot Snapshot = null; try { //converts the URL into a MD5 string, and then takes this MD5 string as key string key = Urltokey (URL); SnapShot = Mdisklrucache.get (key); } catch (Exception e) { e.printstacktrace (); } if (snapShot! = null) { LOG.D (TAG, "Discovery cache:" + URL); InputStream is = snapshot.getinputstream (0); Bitmap Bitmap = Bitmapfactory.decodestream (is); LOG.D (TAG, "read bitmap from cache."); return bitmap; } else return null; }
Write a complete, simple illustration. A imageview,imageview need to load a Web image that is my csdn blog avatar. Example, after the code is started, when loading the network picture for ImageView, the local disklrucache will first check if there is a cache, if there is a direct use of the cache, if not, then re-open a thread to download the picture resources, after the picture download is complete, On the one hand to set to ImageView, while the picture data to write to the Disklrucache cache.
Package Zhangphil.app;import Android.content.context;import Android.content.pm.packageinfo;import Android.content.pm.packagemanager;import Android.graphics.bitmap;import Android.graphics.bitmapfactory;import Android.os.environment;import Android.os.handler;import Android.os.message;import Android.support.v7.app.appcompatactivity;import Android.os.bundle;import Android.util.log;import Android.widget.imageview;import Com.jakewharton.disklrucache.disklrucache;import Java.io.BufferedInputStream; Import Java.io.bytearrayoutputstream;import java.io.file;import java.io.inputstream;import java.io.OutputStream; Import Java.net.httpurlconnection;import Java.net.url;import Java.security.messagedigest;import Java.security.nosuchalgorithmexception;import Java.util.concurrent.executorservice;import Java.util.concurrent.executors;public class Mainactivity extends Appcompatactivity {private Handler Handler; Private Executorservice pool; The default thread pool capacity private int default_task_number = 10; Private final int what = 0xe001; Private String TAG = "Zhangphil_tag"; Private String UNIQUENAME = "Zhangphil_cache"; Private Disklrucache Mdisklrucache = null; Cache size private int disk_cache_max_size = 10 * 1024 * 1024; @Override protected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate); Setcontentview (R.layout.activity_main); Initialize Disklrucache, create Disklrucache instance Makedisklrucache (); Create a thread pool with a capacity of asynctasknumber. Pool = Executors.newfixedthreadpool (Default_task_number); Final ImageView image = (ImageView) Findviewbyid (r.id.image); Handler = new Handler () {@Override public void Handlemessage (Message msg) {switch ( Msg.what) {case WHAT:image.setImageBitmap ((Bitmap) msg.obj); } } }; A test URL connection to download a picture from this link loaded into ImageView String Image_url = "Http://avatar.csdn.neT/9/7/a/1_zhangphil.jpg "; Getbitmap (Image_url); } private void Getbitmap (String URL) {//first read cache from Disklrucache, cache if there is a picture cache for that URL Bitmap bmp = Readbitmapfromdi Sklrucache (URL); if (BMP = = null) {//If not in the cache, create a thread to download the threads T = new downloadthread (URL); Put the thread in the thread pool to download pool.execute (t); } else {//found in Disklrucache cache, direct multiplexing of Sendresult (BMP); }}//read cache from Disklrucache private Bitmap readbitmapfromdisklrucache (String URL) {disklrucache.snapshot SNA Pshot = null; try {//converts the URL into a MD5 string, and then takes this MD5 string as key string key = Urltokey (URL); SnapShot = Mdisklrucache.get (key); } catch (Exception e) {e.printstacktrace (); } if (snapShot! = null) {LOG.D (TAG, "Discovery cache:" + URL); InputStream is = snapshot.getinputstream (0); Bitmap Bitmap = Bitmapfactory.decodestream (IS); LOG.D (TAG,"read from cache bitmap."); return bitmap; } else return null; }//write byte bytes to cache disklrucache private void Writetodisklrucache (String URL, byte[] buf) throws Exception {LOG.D (TAG, url + ": Start write Cache ..."); Disklrucache cache requires a key, I first convert the URL into a MD5 string,//and then use the MD5 string as the key key string Key=urltokey (URL); Disklrucache.editor Editor = Mdisklrucache.edit (key); OutputStream os = editor.newoutputstream (0); Os.write (BUF); Os.flush (); Editor.commit (); Mdisklrucache.flush (); LOG.D (TAG, url + ": Write Cache complete."); private void Makedisklrucache () {try {File Cachedir = Getdiskcachedir (this, UNIQUENAME); if (!cachedir.exists ()) {LOG.D (TAG, "cache directory does not exist, create ..."); Cachedir.mkdirs (); } else Log.d (TAG, "the cache directory already exists and does not need to be created."); The second parameter I choose the version of the app code. Disklrucache if the second parameter version is found to be different, destroy the cache//third parameter is 1, in the write cache stream, Newoutputstream (0), 0 is an index, an array-like subscript Mdisklrucache = Disklrucache.open (Cachedir, Getversioncode (this), 1, disk_cache_max_size); } catch (Exception e) {e.printstacktrace (); }}//Open a download thread private class Downloadthread extends thread {private String URL; Public downloadthread (String url) {this.url = URL; } @Override public void Run () {try {byte[] imagebytes = loadrawdatafromurl (URL); The data is downloaded and the new bitmap data is written to the Disklrucache cache Writetodisklrucache (URL, imagebytes); Bitmap bmp = Bitmapfactory.decodebytearray (imagebytes, 0, imagebytes.length); Sendresult (BMP); } catch (Exception e) {e.printstacktrace (); }}}//Send message notification: Bitmap has been downloaded to completion. private void Sendresult (Bitmap Bitmap) {Message message = Handler.obtainmessage (); Message.what = what; Message.obj = bitmap; HaNdler.sendmessage (message); }//download raw data from a URL, this example is a picture resource. Public byte[] Loadrawdatafromurl (String u) throws Exception {log.d (TAG, "Start download" + u); URL url = new URL (u); HttpURLConnection conn = (httpurlconnection) url.openconnection (); InputStream is = Conn.getinputstream (); Bufferedinputstream bis = new Bufferedinputstream (IS); Bytearrayoutputstream BAOs = new Bytearrayoutputstream (); Final int buffer_size = 2048; Final int EOF =-1; int C; byte[] buf = new Byte[buffer_size]; while (true) {c = Bis.read (BUF); if (c = = EOF) break; Baos.write (buf, 0, C); } conn.disconnect (); Is.close (); byte[] data = Baos.tobytearray (); Baos.flush (); LOG.D (TAG, "Download done!" + u); return data; }/* * When the SD card is present or the SD card is not removable, call the Getexternalcachedir () method to get the cache path, or call the Getcachedir () method to get the cache path. * The former acquires/SDCARD/ANDROID/DAta/<application Package>/cache * The latter acquired/data/data/<application Package>/cache. * * * */Public File Getdiskcachedir (context context, string uniqueName) {string cachepath = null; if (Environment.MEDIA_MOUNTED.equals (Environment.getexternalstoragestate ()) | |! Environment.isexternalstorageremovable ()) {CachePath = Context.getexternalcachedir (). GetPath (); } else {CachePath = Context.getcachedir (). GetPath (); } File Dir = new file (CachePath + file.separator + uniqueName); LOG.D (TAG, "cache directory:" + Dir.getabsolutepath ()); return dir; }//Version name public static String Getversionname (context context) {return Getpackageinfo (context). Versionname; }//version number public static int Getversioncode (context context) {return Getpackageinfo (context). Versioncode; } private static PackageInfo Getpackageinfo (context context) {PackageInfo pi = null; try {PackaGemanager pm = Context.getpackagemanager (); Pi = Pm.getpackageinfo (Context.getpackagename (), packagemanager.get_configurations); return pi; } catch (Exception e) {e.printstacktrace (); } return pi; } public string Urltokey (string url) {return getMD5 (URL); }/* * Pass in a string of strings MSG, returning the Java MD5 encrypted 16 binary string result. * Result shape: c0e84e870874dd37ed0d164c7986f03a */public static String GetMD5 (String msg) {MessageDigest MD = null; try {md = messagedigest.getinstance ("MD5"); } catch (NoSuchAlgorithmException e) {e.printstacktrace (); } md.reset (); Md.update (Msg.getbytes ()); byte[] bytes = Md.digest (); String result = ""; for (byte b:bytes) {//byte converted to 16 binary result + = String.Format ("%02x", b); } return result; }}
When it comes to Android network operation and storage device read and write, do not forget to add the relevant permissions:
< Create and delete file permissions!--sdcard--- <uses-permission android:name= "android.permission.MOUNT_UNMOUNT_ Filesystems "/> <!--write data to SDcard permissions-- <uses-permission android:name=" Android.permission.WRITE _external_storage "/> <uses-permission android:name=" Android.permission.INTERNET "></ Uses-permission>
Appendix Article:
1, "Java LinkedList, implement Android Big Data cache policy" link address: http://blog.csdn.net/zhangphil/article/details/44116885
2, "replace SoftReference cache image with new LRUCache, Android load image asynchronously" link address: http://blog.csdn.net/zhangphil/article/details/43667415
3, "Using Android new LRUCache cache image, based on the thread pool loading pictures Asynchronously" link address: http://blog.csdn.net/zhangphil/article/details/44082287
4, "Java MD5 (String)" link address: http://blog.csdn.net/zhangphil/article/details/44152077
5, "Download raw data from a URL, byte-based" link address: http://blog.csdn.net/zhangphil/article/details/43794837
6, "Android Get App version number and version name" link Address: http://blog.csdn.net/zhangphil/article/details/43795099
Cache Disklrucache on physical storage media for Android level two cache