1. Introduction
Android applications are now inevitable to use the picture, some pictures can be changed, need to start each time from the network pull, this scene in the use of advertising and pure picture applications (such as Baidu Beauty shoot) more.
Now there is a problem: if every time you start pulling pictures from the network, it is bound to consume a lot of traffic. In the current situation, for non-wifi users, traffic is still very expensive, a very traffic-intensive applications, its user order of magnitude is sure to be affected. Of course, I think, to Baidu beauty shoot such an application, must also have its internal image caching strategy. In short, picture caching is important and necessary.
2. The principle of image caching
It is not difficult to achieve the image cache, it is necessary to have the corresponding cache strategy. Here I use the memory-file-network three-layer cache mechanism, where the memory cache includes strong reference cache and soft reference cache (SoftReference), in fact, the network is not a cache, where it is also zoned to the cached hierarchy. When you pull the picture from the network according to the URL, look in the memory, if not in memory, and then from the cache file, if not in the cache file, and then pull the image from the network through the HTTP request. In the key value pair (Key-value), the image cache key is the hash value of the picture URL, value is bitmap. So, according to this logic, as long as a URL is downloaded, its picture is cached.
For soft references to objects in Java (SoftReference), if an object has a soft reference and enough memory space, the garbage collector will not recycle it; if there is not enough memory, the memory of those objects will be reclaimed. The object can be used by the program as long as the garbage collector does not recycle it. Soft references can be used to implement memory-sensitive caching. Using soft references can prevent memory leaks and enhance the robustness of your programs.
From the code, a imagemanager is used to manage and cache the picture, and the function interface is public void LoadBitmap (String url, Handler Handler), where the URL is the picture address to download. Handler a successful callback for a picture download, processing the message in handler, and messages containing information about the picture and bitmap objects. The Imagememorycache (memory cache), Imagefilecache (file cache), and LRUCache (the most recent unused cache) used in Imagemanager are described in subsequent articles.
3. Code Imagemanager.java
Copy Code code as follows:
/*
* Picture Management
* Get the picture asynchronously, call the LoadImage () function directly, the function itself to determine whether the cache or Network load
* Sync get the picture, call the Getbitmap () function directly, the function itself to determine whether from the cache or Network load
* Get pictures from local only, call Getbitmapfromnative ()
* Load pictures from the network only, call Getbitmapfromhttp ()
*
*/
public class Imagemanager implements Imanager
{
Private final static String TAG = "Imagemanager";
Private Imagememorycache Imagememorycache; Memory Cache
Private Imagefilecache Imagefilecache; File caching
The image list being downloaded
public static hashmap<string, handler> Ongoingtaskmap = new hashmap<string, handler> ();
List of image waiting to download
public static hashmap<string, handler> Waitingtaskmap = new hashmap<string, handler> ();
Number of threads downloading pictures at the same time
Final static int max_download_image_thread = 4;
Private final Handler Downloadstatushandler = new Handler () {
public void Handlemessage (msg)
{
Startdownloadnext ();
}
};
Public Imagemanager ()
{
Imagememorycache = new Imagememorycache ();
Imagefilecache = new Imagefilecache ();
}
/**
* Get pictures, multi-threaded entry
*/
public void LoadBitmap (String url, Handler Handler)
{
Get from the memory cache first, take the direct load
Bitmap Bitmap = getbitmapfromnative (URL);
if (bitmap!= null)
{
LOGGER.D (TAG, "loadbitmap:loaded from native");
Message msg = Message.obtain ();
Bundle Bundle = new Bundle ();
bundle.putstring ("url", url);
Msg.obj = bitmap;
Msg.setdata (bundle);
Handler.sendmessage (msg);
}
Else
{
LOGGER.D (TAG, "Loadbitmap:will Load by Network");
Downloadbmponnewthread (URL, handler);
}
}
/**
* New Thread Download picture
*/
private void Downloadbmponnewthread (final String URL, final Handler Handler)
{
LOGGER.D (TAG, "Ongoingtaskmap ' size=" + ongoingtaskmap.size ());
if (Ongoingtaskmap.size () >= max_download_image_thread)
{
Synchronized (WAITINGTASKMAP)
{
Waitingtaskmap.put (URL, handler);
}
}
Else
{
Synchronized (ONGOINGTASKMAP)
{
Ongoingtaskmap.put (URL, handler);
}
New Thread ()
{
public void Run ()
{
Bitmap bmp = Getbitmapfromhttp (URL);
Whether or not the download is successful, it is removed from the download queue, and then the business logic determines if it is to be downloaded again
The download picture uses the httpclientrequest, itself has already brought the heavy link mechanism
Synchronized (ONGOINGTASKMAP)
{
Ongoingtaskmap.remove (URL);
}
if (Downloadstatushandler!= null)
{
Downloadstatushandler.sendemptymessage (0);
}
Message msg = Message.obtain ();
Msg.obj = BMP;
Bundle Bundle = new Bundle ();
bundle.putstring ("url", url);
Msg.setdata (bundle);
if (handler!= null)
{
Handler.sendmessage (msg);
}
}
}.start ();
}
}
/**
* from memory, cache files, load a single bitmap on the network, regardless of threading problem
*/
Public Bitmap getbitmap (String URL)
{
Get pictures from the memory cache
Bitmap Bitmap = imagememorycache.getbitmapfrommemory (URL);
if (bitmap = null)
{
Get in File cache
Bitmap = imagefilecache.getimagefromfile (URL);
if (bitmap!= null)
{
Add to memory Cache
Imagememorycache.addbitmaptomemory (URL, bitmap);
}
Else
{
Getting from the network
Bitmap = getbitmapfromhttp (URL);
}
}
return bitmap;
}
/**
* Get bitmap from memory or cached files
*/
Public Bitmap getbitmapfromnative (String URL)
{
Bitmap Bitmap = null;
Bitmap = imagememorycache.getbitmapfrommemory (URL);
if (bitmap = null)
{
Bitmap = imagefilecache.getimagefromfile (URL);
if (bitmap!= null)
{
Add to memory Cache
Imagememorycache.addbitmaptomemory (URL, bitmap);
}
}
return bitmap;
}
/**
* Download pictures over the network, not related to threads
*/
Public Bitmap getbitmapfromhttp (String URL)
{
Bitmap bmp = null;
Try
{
byte[] tmppicbyte = getimagebytes (URL);
if (tmppicbyte!= null)
{
BMP = Bitmapfactory.decodebytearray (tmppicbyte, 0,
Tmppicbyte.length);
}
Tmppicbyte = null;
}
catch (Exception e)
{
E.printstacktrace ();
}
if (BMP!= null)
{
Add to File Cache
Imagefilecache.savebitmaptofile (BMP, URL);
Add to memory Cache
Imagememorycache.addbitmaptomemory (URL, BMP);
}
return BMP;
}
/**
* Download the linked picture resources
*
* @param URL
*
* @return Pictures
*/
Public byte[] getimagebytes (String URL)
{
byte[] pic = null;
if (URL!= null &&! "". Equals (URL))
{
Requester request = Requesterfactory.getrequester (
Requester.request_remote, REQUESTERFACTORY.IMPL_HC);
Execute request
Myresponse myresponse = null;
Myrequest mmyrequest;
Mmyrequest = new Myrequest ();
Mmyrequest.seturl (URL);
Mmyrequest.addheader (HttpHeader.REQ.ACCEPT_ENCODING, "identity");
InputStream is = null;
Bytearrayoutputstream BAOs = null;
try {
Myresponse = Request.execute (mmyrequest);
is = Myresponse.getinputstream (). Getimpl ();
BAOs = new Bytearrayoutputstream ();
Byte[] B = new byte[512];
int len = 0;
while (len = Is.read (b))!=-1)
{
Baos.write (b, 0, Len);
Baos.flush ();
}
pic = Baos.tobytearray ();
LOGGER.D (TAG, "icon bytes.length=" + pic.length);
}
catch (Exception E3)
{
E3.printstacktrace ();
Try
{
LOGGER.E (TAG,
"Download shortcut icon faild and responsecode="
+ Myresponse.getstatuscode ());
}
catch (Exception E4)
{
E4.printstacktrace ();
}
}
Finally
{
Try
{
if (is!= null)
{
Is.close ();
is = null;
}
}
catch (Exception E2)
{
E2.printstacktrace ();
}
Try
{
if (BAOs!= null)
{
Baos.close ();
BAOs = null;
}
}
catch (Exception E2)
{
E2.printstacktrace ();
}
Try
{
Request.close ();
}
catch (Exception E1)
{
E1.printstacktrace ();
}
}
}
return pic;
}
/**
* Take out waiting queue first task, start downloading
*/
private void Startdownloadnext ()
{
Synchronized (WAITINGTASKMAP)
{
LOGGER.D (TAG, "begin start Next");
Iterator iter = Waitingtaskmap.entryset (). iterator ();
while (Iter.hasnext ())
{
Map.entry Entry = (map.entry) iter.next ();
LOGGER.D (TAG, "Waitingtaskmap isn ' t null,url=" + (String) Entry.getkey ());
if (entry!= null)
{
Waitingtaskmap.remove (Entry.getkey ());
Downloadbmponnewthread ((String) Entry.getkey (), (Handler) Entry.getvalue ());
}
Break
}
}
}
Public String startdownloadnext_forunittest ()
{
String urlstring = null;
Synchronized (WAITINGTASKMAP)
{
LOGGER.D (TAG, "begin start Next");
Iterator iter = Waitingtaskmap.entryset (). iterator ();
while (Iter.hasnext ())
{
Map.entry Entry = (map.entry) iter.next ();
URLString = (String) entry.getkey ();
Waitingtaskmap.remove (Entry.getkey ());
Break
}
}
return urlstring;
}
/**
* The picture turns round corner
* @param bitmap: Incoming bitmap
* @param pixels: The degree of fillet, the greater the value, the greater the rounded corners
* @return Bitmap: Bitmap with rounded corners
*/
public static Bitmap Toroundcorner (Bitmap Bitmap, int pixels)
{
if (bitmap = null)
return null;
Bitmap output = Bitmap.createbitmap (Bitmap.getwidth (), Bitmap.getheight (), config.argb_8888);
Canvas Canvas = new Canvas (output);
final int color = 0xff424242;
Final Paint Paint = new Paint ();
Final Rect Rect = new Rect (0, 0, bitmap.getwidth (), Bitmap.getheight ());
Final RECTF RECTF = new RECTF (rect);
Final float roundpx = pixels;
Paint.setantialias (TRUE);
Canvas.drawargb (0, 0, 0, 0);
Paint.setcolor (color);
Canvas.drawroundrect (RECTF, ROUNDPX, ROUNDPX, paint);
Paint.setxfermode (New Porterduffxfermode (mode.src_in));
Canvas.drawbitmap (Bitmap, rect, rect, paint);
return output;
}
Public byte ManagerID ()
{
return image_id;
}
}