Previously in Guo Dashin's blog saw the use of the LRUCache algorithm to implement the image cache. Here, imitating his ideas, he wrote a. and join Concurrenthashmap<string, softreference<bitmap>> to implement level two cache, because Concurrenthashmap is a thread safe for multiple locks, Supports high concurrency. This is ideal for frequent access to memory-read operations.
The whole idea is to use the system-provided LRUCache class to do a first-level cache, the size of the running memory of 1/8, when the LRUCache capacity is full, will automatically put the system to remove the picture in the two cache, but in order to avoid the problem of Oom, The SoftReference soft reference is added here, and when the system is about to go to Oom, it will automatically erase the memory of the image inside, and of course the memory will continue to save these two-level cached images. Emphasize, do not use SoftReference to do the first level cache, Garbage collection in Java now strengthens the recycling mechanism for SoftReference soft references, which are only suitable for temporary storage of some data caches and are not suitable for long-term (relatively temporary, not real-time).
Directly on the code, take it to use it:
/** * Created on 3/11/2015 * <br> picture Asynchronous Loading tool (supports local picture loading, Web image URL and Project image resource loading) * <br> Dual cache support: LRUCache and SoftReference * @ Author Mr.et * */public class Imageloadmanager {/** picture Source type: file, network, resource ID **/public enum IMAGE_LOAD_TYPE{FILE_PATH,FILE_URL,F Ile_resource_id}private String TAG = "Imageloadmanager ...";p rivate Context context;private set<imageloadtask> taskcollection;/** maximum memory **/final static int maxcachesize = (int) (Runtime.getruntime (). MaxMemory ()/8);/** Establish thread safety, Supports highly concurrent containers **/private static concurrenthashmap<string, softreference<bitmap>> currenthashmap= New Concurrenthashmap<string, softreference<bitmap>> ();p ublic Imageloadmanager (context context) {super (); This.context = Context;taskcollection = new hashset<imageloadmanager.imageloadtask> ();} private static lrucache<string, bitmap> Bitmapmemorycache = new lrucache<string, bitmap> (maxcachesize) {@ overrideprotected int sizeOf (String key, Bitmap value) {if (value! = null) {return value.getbytecount();//return value.getrowbytes () * value.getheight ();//old version of method}else{return 0;}} This method is called when the memory capacity of the LRUCache is full, and the oldvalue element is removed to make room for the new element to join @overrideprotected void Entryremoved (Boolean evicted, String key,bitmap OldValue, Bitmap newvalue) {if (oldValue! = null) {///when the hard-reference cache capacity is full, the LRU algorithm is used to transfer pictures that have not been used recently to the soft-reference cache Currenthas Hmap.put (Key, New softreference<bitmap> (OldValue));}}};/ * * * for displaying pictures with image resource ID * @param loadtype picture Load type * @param imageresourceid picture Resource ID * @param imageview show picture ImageView */public V OID Setimageview (image_load_type loadtype, int imageresourceid, ImageView ImageView) {if (Loadtype = = Image_load_type. file_resource_id) {//if (Ifresourceidexist (Imageresourceid))//{//imageview.setimageresource (ImageResourceID);/// /}else{//map cannot get the picture, the default picture//imageview.setimageresource (R.drawable.pic_default) is displayed;//}try { Imageview.setimageresource (Imageresourceid); return;} catch (Exception e) {log.e (TAG, "Can find the ImageID of" +imageresourceid); E.printstacktrace ();} Default Picture Imageview.setimageresource (R.drawable.piC_default);}} /** * How to display pictures with a link to a picture file or a download link * @param loadtype picture Load type * @param imagefilepath the local file address of the picture file or the download link for the network URL * @param imageview display diagram ImageView */public void Setimageview (Image_load_type loadtype, String Imagefilepath, ImageView ImageView) {if ( Imagefilepath = = NULL | | Imagefilepath.trim (). Equals ("")) {Imageview.setimageresource (r.drawable.pic_default);} Else{bitmap Bitmap = Getbitmapfrommemorycache (Imagefilepath); if (Bitmap! = null) {Imageview.setimagebitmap (Bitmap);} Else{imageview.setimageresource (r.drawable.pic_default); Imageloadtask task = new Imageloadtask (LoadType, ImageView) ; Taskcollection.add (Task); Task.execute (Imagefilepath);}} /** * Gets a picture from LRUCache and returns null if it does not exist * @param key value can be a filepath of a picture file, can be a picture URL address * @return Bitmap object, or null */public Bitmap Getbitmapfrommemorycache (String key) {try {if (bitmapmemorycache.get (key) = = null) {if (Currenthashmap.get (key) = null) {return Currenthashmap.get (key). get ();}} return Bitmapmemorycache.get (key);} catch (Exception e) {e.printstacktrace ();} ReTurn bitmapmemorycache.get (key);} /** * Put the picture in the cache * @param key * @param bitmap */private void Addbitmaptocache (String key, bitmap bitmap) {Bitmapmemorycache.pu T (key, bitmap);} /** * Picture Asynchronous Load * @author Mr.et * */private class Imageloadtask extends Asynctask<string, Void, Bitmap>{private String Imagepath;private ImageView imageview;private image_load_type loadtype;public imageloadtask (IMAGE_LOAD_TYPE loadType , ImageView ImageView) {this.loadtype = Loadtype;this.imageview = ImageView;} @Overrideprotected Bitmap Doinbackground (string...params) {ImagePath = params[0];try {if (Loadtype = = Image_load_type. File_path) {if (new File (ImagePath). Exists ()) {//Read pictures from local File bitmapfactory.options opts = new Bitmapfactory.options (); O Pts.insamplesize = 2; Bitmap Bitmap = Bitmapfactory.decodefile (ImagePath, opts);//The new picture to be acquired is put into the cache Addbitmaptocache (ImagePath, Bitmap); return Bitmap;} return null;} else if (Loadtype = = Image_load_type. File_url) {//download picture from Network byte[] datas = Getbytesofbitmap (ImagePath); if (datas! = null) {//BITMAPFACTory. Options opts = new Bitmapfactory.options ();//opts.insamplesize = 2;//bitmap Bitmap = Bitmapfactory.decodebytearray ( Datas, 0, Datas.length, opts); Bitmap Bitmap = Bitmapfactory.decodebytearray (datas, 0, datas.length); Addbitmaptocache (ImagePath, Bitmap); return Bitmap;} return null;}} catch (Exception e) {e.printstacktrace (); Fileutils.saveexceptionlog (e);//can customize other operations}return null;} @Overrideprotected void OnPostExecute (Bitmap Bitmap) {try {if (ImageView! = null) {if (Bitmap! = null) { Imageview.setimagebitmap (bitmap);} ELSE{LOG.E (TAG, "The bitmap result is null ...");} ELSE{LOG.E (TAG, "The ImageView is null ...");//The default picture Imageview.setimageresource (R.drawable.pic_default) is displayed when the picture fails;}} catch (Exception e) {e.printstacktrace (); Fileutils.saveexceptionlog (e);}} /** * InputStream Turn byte[] * @param instream * @return * @throws Exception */private byte[] Readstream (InputStream instream) Throws exception{Bytearrayoutputstream OutStream = new Bytearrayoutputstream (); byte[] buffer = new BYTE[2048]; int len = 0; while ((Len=instream.read (buffer))! =-1) {outstream.write (buffer, 0, Len); } outstream.close (); Instream.close (); return Outstream.tobytearray (); }/** * Get download image and switch to byte[] * @param urlstr * @return */private byte[] Getbytesofbitmap (String imgurl) {try {URL url = new URL (i Mgurl); HttpURLConnection conn = (httpurlconnection) url.openconnection (); Conn.setconnecttimeout (10 * 1000); 10sconn.setreadtimeout (20 * 1000); Conn.setrequestmethod ("GET"); Conn.connect (); InputStream in = Conn.getinputstream (); Return Readstream (in);} catch (IOException e) {e.printstacktrace ();} catch (Exception e) {e.printstacktrace ();} return null;} /** * The resource ID is valid * @param resourceId resource ID * @return */private boolean ifresourceidexist (int resourceId) {try {Field field = R.drawable.class.getfield (string.valueof (resourceId)); Integer.parseint (Field.get (null). ToString ()); return true; catch (Exception e){E.printstacktrace ();} return false;} /** * Cancel All Tasks */public void Cancelalltask () {if (taskcollection! = null) {for (Imageloadtask task:taskcollection) { Task.cancel (FALSE);}}}
In addition, if you need a more perfect experience, you can also add a third-level caching mechanism, such as caching the picture to a local disk storage space. But don't want these cached local images to be scanned by other apps or seen by users? Here are a few ideas, such as converting a picture to a string store with an encryption algorithm, or converting a picture to an unknown file in a custom format in a hidden place (many applications have taken this approach). This is the way to try to achieve it yourself oh ~
Android performance optimized for dual-cached images asynchronous load tool (Lrucache+softreference)-Ready to use