LRU algorithm for Android image caching (ii) _android

Source: Internet
Author: User
Tags flush

Objective:
In the last chapter we summarize the processing of bitmap, compare the efficiency of various processing and the memory footprint, click View. We learned that if a application uses a large number of pictures to cause oom (out of memory), how can it be handled to reduce the probability of oom happening nearly? We've been using softreference soft references all the time, SoftReference is a way that is no longer recommended because the garbage collector, starting with the Android 2.3 (API Level 9), is more inclined to reclaim objects that hold soft references or weak references. This makes soft references less reliable, so today we come to a new cache processing algorithm LRU, and then learn about LRU based LRUCache, disklrucache implementation of our image caching.

Lru:
LRU is least recently Used abbreviation, translation is "least recently used", the LRU cache is the use of this principle to achieve, simply to cache a certain amount of data, when more than the set threshold to delete some outdated data, such as we cache 10,000 of data, When the data is less than 10000, you can add it randomly. When more than 10000 of the need to add new data, but also to delete the outdated data to ensure that we have the largest cache of 10,000, then how to determine the deletion of the expiration of the data, the use of LRU algorithm to achieve the most old data deleted.

Implementing memory caching based on LRUCache:
1. Initialization of MemoryCache
Here the memory cache is drawable rather than bitmap reason is that drawable has a great memory advantage over bitmap

 int maxmemory = (int) runtime.getruntime (). MaxMemory ()//Get the total memory size of the system allocated to the application
 int mcachesize = maxmemory/8;// Set picture memory cache occupancy One-eighth
 mmemorycache = new lrucache<string, drawable> (mcachesize) {
  //You must override this method to measure the size of the bitmap
  @Override
  protected int sizeOf (String key, drawable value) {
  if (value instanceof bitmapdrawable) {
   Bitmap Bitmap = ((bitmapdrawable) value). Getbitmap ();
   return bitmap = null? 0:bitmap.getbytecount ();
  }
  Return super.sizeof (key, value);
  }
 ;

2.) Add a drawable to the memory cache

 /**
 * Add drawable to memory Cache
 * *
 @param key
 * @param drawable
 /
 private void Adddrawabletomemorycache (String key, drawable drawable) {
 if (getdrawablefrommemcache (key) = = NULL && drawable!= null) {
  mmemorycache.put (key, drawable);
 }
 }

3.) obtain a drawable from the memory cache

 /**
 * Gets a drawable
 * *
 @param key * @return/public
 drawable Getdrawablefrommemcache from the memory cache (String key) {return
 mmemorycache.get (key);
 }

4.) Remove a drawable from the memory cache

 /**
 * Removed from the memory cache
 * *
 @param key
 /public
 void Removecachefrommemory (String key) {
 Mmemorycache.remove (key);
 }

5.) Empty the memory cache

 /**
 * Clean Memory cache
 /public void Cleanmemoryccache () {
 mmemorycache.evictall ();
 } 

In fact, the LRU caching mechanism is essentially stored in a linkedhashmap storage, in order to ensure the insertion of data order, easy to clean.

Implementing disk caching based on Disklrucache:
Disklrucache class is not Google official implementation, need to download, download address:Https://github.com/JakeWharton/DiskLruCache

1. Initialization of Disklrucache

 File Cachedir = Context.getcachedir ()//specified is the cached address of the data
 long diskcachesize = 1024 * 1024 * 30;//The maximum number of bytes that can be cached
 int app Version = Disklruutils.getappversion (context);//Specifies the current application's build number
 int valuecount = 1;//Specifies how many cached file
 try {The same key can correspond to
  Mdiskcache = Disklrucache.open (Cachedir, appversion, Valuecount, diskcachesize);
 catch (Exception ex) {
 }

2.) write a file to the disk cache

 /**
 * Add bitmap to disk cache
 *
 @param key
 * @param value *
 /private void Addbitmaptodiskcache (String Key, byte[] value {
 outputstream out = null;
 try {
  Disklrucache.editor Editor = Mdiskcache.edit (key);
  if (editor!= null) {Out
  = editor.newoutputstream (0);
  if (value!= null && value.length > 0) {
   out.write (value);
   Out.flush ();
   Editor.commit ();
  } else {
   editor.abort ();
  }
  }
  Mdiskcache.flush ();
 } catch (IOException e) {
  e.printstacktrace ();
 } finally {
  disklruutils.closequietly (out);
 }
 }

3.) Read the drawable from the disk cache

 /**
 * Get a drawable * *
 @param key * @return/public
 drawable from the disk cache Getdrawablefromdiskcache (String key) {
 try {
  disklrucache.snapshot Snapshot = Mdiskcache.get (key);
  if (snapShot!= null) {
  InputStream is = snapshot.getinputstream (0);
  Bitmap Bitmap = Bitmapfactory.decodestream (is);
  drawable drawable = disklruutils.bitmap2drawable (bitmap);
  Add the memory cache
  Adddrawabletomemorycache (key, drawable) after reading from disk;
  Return drawable
  }
 } catch (IOException e) {
  e.printstacktrace ();
 }
 return null;
 }

4.) Remove from the disk cache

 /**
 * Remove from disk cache * *
 @param key/public
 void Removecachefromdisk (String key) {
 try {
  Mdiskcache.remove (key);
 } catch (Exception e) {
 }
 }

5.) Empty the disk cache

 /**
 * Clean disk cache/public
 void Cleandiskcache () {
 try {
  mdiskcache.delete ();
 } catch (Exception E ) {
 }
 }


Picture Download Process:
the next instance uses a bit of rxjava knowledge to understand Rxjava.
1. Asynchronous operation of disk cache and network download, memory cache can be operated in the main thread

 public void DisPlay (final ImageView ImageView, String imageUrl) {//Generate unique key final String key = Disklruutils.hashkeyf
  Ordisk (IMAGEURL);
  Read drawable Drawablefrommemcache = Getdrawablefrommemcache (key) from memory first;
   if (Drawablefrommemcache!= null) {imageview.setimagedrawable (Drawablefrommemcache);
  Return Observable.just (IMAGEURL). Map (new func1<string, drawable> () {@Override public drawable call (stri
      ng ImageUrl) {//Parameter type String//read from disk drawable Drawablefromdiskcache = Getdrawablefromdiskcache (key);
      if (Drawablefromdiskcache!= null) {return drawablefromdiskcache; }//Network download return download (IMAGEURL); return type drawable}}). Subscribeon (Schedulers.io ())//Specifies that subscribe () occurs in IO threads. Observeon (Androidschedul Ers.mainthread ())//Specifies that the subscriber callback occurs on the main thread. Subscribe (new action1<drawable> () {@Override public voi D Call (drawable drawable) {//parameter type drawable Imageview.setiMagedrawable (drawable);
 }
    });
 }

2.) Download picture process and deal with

 Private drawable Download (String imageUrl) {httpurlconnection urlconnection = null;
  Bytearrayoutputstream BOS = NULL;
  InputStream ins = null;
   Try {final URL url = new URL (imageUrl);
   URLConnection = (httpurlconnection) url.openconnection ();
   INS = Urlconnection.getinputstream ();
   BOS = new Bytearrayoutputstream ();
   int b;
   while ((b = ins.read ())!=-1) {bos.write (b);
   } bos.flush ();
   byte[] bytes = Bos.tobytearray ();
   Bitmap Bitmap = disklruutils.bytes2bitmap (bytes);
   String key = Disklruutils.hashkeyfordisk (IMAGEURL);
   drawable drawable = disklruutils.bitmap2drawable (bitmap);
   Add memory Cache Adddrawabletomemorycache (key, drawable);
   Add disk cache Addbitmaptodiskcache (key, bytes);
  return drawable;
  catch (IOException e) {e.printstacktrace ();
   finally {if (urlconnection!= null) {urlconnection.disconnect ();
   disklruutils.closequietly (BOS);
  disklruutils.closequietly (INS);
 return null;

 }

Attach final picture Ease of receipt example simple implementation of all code and Disklruutils tool class code
Imageloadmanager.java

public class Imageloadmanager {private lrucache<string, drawable> mmemorycache;//memory cache private Disklrucache MDisk cache;//disk Cache private static Imageloadmanager minstance;//get picture Download single Case Reference/** * constructor * * @param context/Private Im Ageloadmanager (context context) {int maxmemory = (int) runtime.getruntime (). MaxMemory ()//Get the total memory size of the system allocated to the application int mcaches ize = maxmemory/8;//Set Picture memory cache occupies one-eighth Mmemorycache = new lrucache<string, drawable> (mcachesize) {//must override this method to measure B
     Itmap size @Override protected int sizeOf (String key, drawable value) {if (value instanceof bitmapdrawable) {
     Bitmap Bitmap = ((bitmapdrawable) value). Getbitmap (); return bitmap = null?
    0:bitmap.getbytecount ();
   Return super.sizeof (key, value);

  }
  }; File Cachedir = Context.getcachedir ()//Specifies the cached address of the data long diskcachesize = 1024 * 1024 * 30;//The maximum number of bytes that can be cached int appversi
 On = disklruutils.getappversion (context);//Specifies the current application's version number int valuecount = 1;//Specifies how many cached files the same key can correspond to try {Mdiskcache = Disklrucache.open (Cachedir, appversion, Valuecount, diskcachesize); catch (Exception ex) {}}/** * Get a Single instance reference * * @return/public static Imageloadmanager getinstance
  Context) {Imageloadmanager Inst = minstance;
    if (inst = = null) {synchronized (requestmanager.class) {inst = minstance;
     if (inst = = null) {inst = new Imageloadmanager (Context.getapplicationcontext ());
    Minstance = Inst;
 }} return inst; public void DisPlay (final ImageView ImageView, String imageUrl) {//Generate unique key final String key = Disklruutils.hashke
  Yfordisk (IMAGEURL);
  Read drawable Drawablefrommemcache = Getdrawablefrommemcache (key) from memory first;
   if (Drawablefrommemcache!= null) {imageview.setimagedrawable (Drawablefrommemcache);
  Return Observable.just (IMAGEURL). Map (new func1<string, drawable> () {@Override public drawable call (stri ng ImageUrl) {//Parameter type String//read from disk drawable DRAWablefromdiskcache = Getdrawablefromdiskcache (key);
      if (Drawablefromdiskcache!= null) {return drawablefromdiskcache; }//Network download return download (IMAGEURL); return type drawable}}). Subscribeon (Schedulers.io ())//Specifies that subscribe () occurs in IO threads. Observeon (Androidschedul Ers.mainthread ())//Specifies that the subscriber callback occurs on the main thread. Subscribe (new action1<drawable> () {@Override public voi
     D Call (drawable drawable) {//Parameter type drawable imageview.setimagedrawable (drawable);
 }
    }); /** * Add drawable to memory Cache * * @param key * @param drawable/private void Adddrawabletomemorycache (String key , drawable drawable) {if (Getdrawablefrommemcache (key) = null && drawable!= null) {Mmemorycache.put (key),
  drawable);  }/** * Gets a drawable * * @param key * @return/Public drawable Getdrawablefrommemcache (String key) from the memory cache
 {return mmemorycache.get (key);
/** * Gets a drawable * * @param key from the disk cache  * @return */public drawable Getdrawablefromdiskcache (String key) {try {disklrucache.snapshot Snapshot = MDisk
   Cache.get (key);
    if (snapShot!= null) {InputStream is = snapshot.getinputstream (0);
    Bitmap Bitmap = Bitmapfactory.decodestream (IS);
    drawable drawable = disklruutils.bitmap2drawable (bitmap);
    Add the memory cache Adddrawabletomemorycache (key, drawable) after reading from disk;
   return drawable;
  } catch (IOException e) {e.printstacktrace ();
 return null; /** * Add bitmap to disk cache * @param key * @param value/private void Addbitmaptodiskcache (String key, byte[] V
  Alue) {outputstream out = null;
   try {disklrucache.editor Editor = Mdiskcache.edit (key);
    if (editor!= null) {out = Editor.newoutputstream (0);
     if (value!= null && value.length > 0) {out.write (value);
     Out.flush ();
    Editor.commit ();
    else {editor.abort ();
  } mdiskcache.flush (); catch (IOException e) {E.printStackTrace ();
  Finally {disklruutils.closequietly (out);
  } private drawable Download (String imageUrl) {httpurlconnection urlconnection = null;
  Bytearrayoutputstream BOS = NULL;
  InputStream ins = null;
   Try {final URL url = new URL (imageUrl);
   URLConnection = (httpurlconnection) url.openconnection ();
   INS = Urlconnection.getinputstream ();
   BOS = new Bytearrayoutputstream ();
   int b;
   while ((b = ins.read ())!=-1) {bos.write (b);
   } bos.flush ();
   byte[] bytes = Bos.tobytearray ();
   Bitmap Bitmap = disklruutils.bytes2bitmap (bytes);
   String key = Disklruutils.hashkeyfordisk (IMAGEURL);
   drawable drawable = disklruutils.bitmap2drawable (bitmap);
   Add memory Cache//Adddrawabletomemorycache (key, drawable);
   Add disk cache Addbitmaptodiskcache (key, bytes);
  return drawable;
  catch (IOException e) {e.printstacktrace ();
   finally {if (urlconnection!= null) {urlconnection.disconnect ();
   disklruutils.closequietly (BOS); Disklruutils.closequietly (INS);
 return null;
  /** * Removed from cache * * @param key/public void RemoveCache (String key) {removecachefrommemory (key);
 Removecachefromdisk (key);
 /** * Removed from the memory cache * * @param key */public void Removecachefrommemory (String key) {mmemorycache.remove (key); /** * Removed from disk cache * * @param key/public void Removecachefromdisk (String key) {try {mdiskcache.remove (
  Key); The catch (Exception e) {}}/** * Disk cache Size * * @return/public long diskcachesize () {return MDISKCACHE.S
 Ize ();
 /** * Memory Cache Size * * @return/public long memorycachesize () {return mmemorycache.size ();
  /** * Turn off disk cache/public void Closediskcache () {try {mdiskcache.close ();
  The catch (Exception e) {}}/** * Cleanup cache/public void Cleancache () {Cleanmemoryccache ();
 Cleandiskcache ();
  /** * Clean disk cache/public void Cleandiskcache () {try {mdiskcache.delete (); catch (Exceptione) {}}/** * scavenging memory Cache/public void Cleanmemoryccache () {mmemorycache.evictall ();

 }
}

Disklruutils.java

Final class Disklruutils {/** * Close input/output stream/public static void closequietly (/*auto*/closeable closeable) {if (c)
   Loseable!= null) {try {closeable.close ();
   catch (RuntimeException rethrown) {throw rethrown; 
  ' catch (Exception ignored) {}}}/** * get Versioncode/public static int Getappversion (context context) {
   try {packageinfo info = Context.getpackagemanager (). Getpackageinfo (Context.getpackagename (), 0);
  return info.versioncode;
  catch (Packagemanager.namenotfoundexception e) {e.printstacktrace ();
 return 1;
  public static string Hashkeyfordisk (String key) {string CacheKey;
   try {final MessageDigest mdigest = messagedigest.getinstance ("MD5");
   Mdigest.update (Key.getbytes ());
  CacheKey = bytestohexstring (Mdigest.digest ());
  catch (NoSuchAlgorithmException e) {cachekey = String.valueof (Key.hashcode ());
 return cachekey; public static String bytestohexstring (byte[] bytes) {StringbuiLder sb = new StringBuilder ();
   for (int i = 0; i < bytes.length i++) {String hex = integer.tohexstring (0xFF & Bytes[i]);
   if (hex.length () = = 1) {sb.append (' 0 ');
  } sb.append (hex);
 return sb.tostring ();
  }/** * Bitmap→bytes/public static byte[] Bitmap2bytes (Bitmap BM) {if (BM = null) {return null;
  } bytearrayoutputstream BAOs = new Bytearrayoutputstream ();
  Bm.compress (Bitmap.CompressFormat.PNG, BAOs);
 return Baos.tobytearray (); }/** * Bytes→bitmap/public static Bitmap bytes2bitmap (byte[] bytes) {return Bitmapfactory.decodebytearray (
 Bytes, 0, bytes.length);
   }/** * Drawable→bitmap/public static Bitmap Drawable2bitmap (drawable drawable) {if (drawable = null) {
  return null;
  ///Take drawable's long width int w = drawable.getintrinsicwidth ();
  int h = drawable.getintrinsicheight (); Take drawable color format bitmap.config Config = drawable.getopacity ()!= pixelformat.opaque? Bitmap.Config.ARGB_8888:bitmap.config.rgb_565;
  Establish corresponding bitmap bitmap bitmap = Bitmap.createbitmap (w, H, config);
  Create the canvas corresponding to the bitmap Canvas Canvas = new Canvas (bitmap);
  Drawable.setbounds (0, 0, W, h);
  Draw the drawable content to the canvas drawable.draw (canvas);
 return bitmap; } * * Bitmap→drawable/public static drawable bitmap2drawable (Bitmap BM) {if (BM = null) {return nul
  L
  } bitmapdrawable bd = new bitmapdrawable (BM);
  Bd.settargetdensity (Bm.getdensity ());
 Return to New bitmapdrawable (BM);

 }

}

  above is based on LRU picture caching simple implementation, I hope to help you learn, but also hope that we support the cloud habitat community.

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.