Android optimized dual cache picture Asynchronous loading tool (Lrucache+softreference)

Source: Internet
Author: User
Tags garbage collection


Previously in Guo Dashin's blog to see Using the LRUCache algorithm to achieve image caching. Here imitate his ideas, he also wrote a. and add concurrenthashmap<string, softreference<bitmap>> to implement level two cache, because Concurrenthashmap is the thread safety of multiple locks, Supports high concurrency. This is a good fit for this frequently accessed read memory operation.


The whole idea is to use the system provided by the LRUCache class to do a level of cache, the size of 1/8 of running memory, when the LRUCache capacity is full, the system will automatically remove the picture into the level two cache, but in order to avoid the problem of Oom, Here will softreference soft reference, when the system is about to Oom automatically erase the image memory inside, of course, when sufficient memory will continue to save these two-level cache of pictures. To emphasize that, do not use the softreference to do a level of cache, Garbage collection in Java now strengthens the recycling mechanism for soft references to SoftReference, which is only suitable for temporary storage of some data caches, and is not suitable for long-term (relatively temporary, not real long-term).


Directly on the code, to get the use of OH:

/**
* Created on 3/11/2015
* <br> Image Asynchronous loading tool (support for local picture loading, Web image URL and project picture resource loading)
* <br> supports dual caching: 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,file_resource_id
}

Private String TAG = "Imageloadmanager ...";

private context;

Private set<imageloadtask> taskcollection;

/** Maximum Memory **/
Final static int maxcachesize = (int) (Runtime.getruntime (). MaxMemory ()/8);

/** establishes thread safety and supports high concurrency containers **/
private static concurrenthashmap<string, softreference<bitmap>> Currenthashmap
= new concurrenthashmap<string, softreference<bitmap>> ();







Public Imageloadmanager
{
Super ();
This.context = context;
Taskcollection = new hashset<imageloadmanager.imageloadtask> ();
}

private static lrucache<string, bitmap> Bitmapmemorycache = new lrucache<string, bitmap> (maxcachesize)
{
@Override
protected int sizeOf (String key, Bitmap value)
{
if (value!= null)
{
return Value.getbytecount ();
return Value.getrowbytes () * Value.getheight (); Old version of the method
}
Else
{
return 0;
}
}

This method is invoked when LRUCache memory is full, removing oldvalue elements to make room for new elements to join
@Override
protected 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 turn the recently unused picture into the soft reference cache
Currenthashmap.put (Key, New softreference<bitmap> (OldValue));
}
}

};

/**
* Methods for displaying pictures with picture resource IDs
* @param loadtype Picture Load Type
* @param imageresourceid Picture Resource ID
* @param imageview Display Picture ImageView
*/
public void 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 is displayed
Imageview.setimageresource (R.drawable.pic_default);
//   }
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);
}
}

/**
* Methods for displaying pictures by linking or downloading links to picture files
* @param loadtype Picture Load Type
* @param imagefilepath The local file address of the picture file or the download link of the network URL
* @param imageview Display Picture 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);
}
}
}

/**
* Get a picture from the LRUCache and return NULL if it does not exist
* @param key value can be a picture file filepath, 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.put (key, bitmap);
}


/**
* Picture Asynchronous loading
* @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;
}

@Override
Protected 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 ();
Opts.insamplesize = 2;
Bitmap Bitmap = Bitmapfactory.decodefile (ImagePath, opts);
Put the new picture you get into the cache
Addbitmaptocache (ImagePath, bitmap);
return bitmap;
}
return null;
}
else if (Loadtype = Image_load_type. File_url)
{//download pictures from the 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 actions
}
return null;
}

@Override
protected 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 ...");
Show default picture when get picture fails
Imageview.setimageresource (R.drawable.pic_default);
}

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 picture and switch to byte[]
* @param urlstr
* @return
*/
Private byte[] Getbytesofbitmap (String imgurl) {
try {
URL url = new URL (imgurl);
HttpURLConnection conn = (httpurlconnection) url.openconnection ();
Conn.setconnecttimeout (10 * 1000); 10s
Conn.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-tier caching mechanism, such as caching images to local disk storage space. But don't want these cached in the local image is scanned by other applications or users see how to do? Here are a few ideas, such as converting images to string storage using encryption algorithms, or moving pictures into a custom format for unknown files in a hidden place (many applications take this approach). This might as well try to achieve it yourself oh ~

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.