In the Android project to access the network picture is very common thing, if we have to access the network every time to get pictures, will be very expensive traffic, and pictures occupy a larger memory space, too many pictures and do not release the words can easily cause memory overflow. For the two problems encountered above, first of all the flow of traffic we can load the first time the image cached to the local, and then directly from the local loading. Too many pictures caused memory overflow, this is the most difficult to solve, to think of some good caching strategies, such as large pictures using the LRU cache policy or lazy load cache policy. Let's start by introducing a local cache picture today.
First look at the asynchronous load cache local code:
Copy Code code as follows:
Publicclassasyncbitmaploader
{
/**
* Memory picture Soft Reference buffer
*/
privatehashmap<string,softreference<bitmap>>imagecache=null;
Publicasyncbitmaploader ()
{
Imagecache=newhashmap<string,softreference<bitmap>> ();
}
Publicbitmaploadbitmap (Finalimageviewimageview,finalstringimageurl,finalimagecallbackimagecallback)
{
In the memory cache, returns the Bitmap object
if (Imagecache.containskey (ImageURL))
{
Softreference<bitmap>reference=imagecache.get (ImageURL);
Bitmapbitmap=reference.get ();
if (bitmap!=null)
{
Returnbitmap;
}
}
Else
{
/**
* Plus a lookup on the local cache
*/
Stringbitmapname=imageurl.substring (Imageurl.lastindexof ("/") +1);
Filecachedir=newfile ("/mnt/sdcard/test/");
File[]cachefiles=cachedir.listfiles ();
inti=0;
if (null!=cachefiles) {
for (; i<cachefiles.length;i++)
{
if (Bitmapname.equals (Cachefiles[i].getname ()))
{
Break
}
}
if (i<cachefiles.length)
{
Returnbitmapfactory.decodefile ("/mnt/sdcard/test/" +bitmapname);
}
}
}
Finalhandlerhandler=newhandler ()
{
/* (Non-javadoc)
* @seeandroid. Os.handler#handlemessage (Android.os.Message)
*/
@Override
Publicvoidhandlemessage (MESSAGEMSG)
{
Todoauto-generatedmethodstub
Imagecallback.imageload (ImageView, (Bitmap) msg.obj);
}
};
If it is not in the memory cache or is not local (reclaimed by the JVM), open the thread to download the picture
Newthread ()
{
/* (Non-javadoc)
* @seejava. Lang.thread#run ()
*/
@Override
Publicvoidrun ()
{
Todoauto-generatedmethodstub
Inputstreambitmapis=httputils.getstreamfromurl (ImageURL);
Bitmapbitmap=bitmapfactory.decodestream (Bitmapis);
Imagecache.put (imageurl,newsoftreference<bitmap> (Bitmap));
Messagemsg=handler.obtainmessage (0,BITMAP);
Handler.sendmessage (msg);
Filedir=newfile ("/mnt/sdcard/test/");
if (!dir.exists ())
{
Dir.mkdirs ();
}
Filebitmapfile=newfile ("/mnt/sdcard/test/" +
Imageurl.substring (Imageurl.lastindexof ("/") +1));
if (!bitmapfile.exists ())
{
Try
{
Bitmapfile.createnewfile ();
}
catch (Ioexceptione)
{
Todoauto-generatedcatchblock
E.printstacktrace ();
}
}
Fileoutputstreamfos;
Try
{
Fos=newfileoutputstream (Bitmapfile);
Bitmap.compress (Bitmap.CompressFormat.PNG,
100,fos);
Fos.close ();
}
catch (Filenotfoundexceptione)
{
Todoauto-generatedcatchblock
E.printstacktrace ();
}
catch (Ioexceptione)
{
Todoauto-generatedcatchblock
E.printstacktrace ();
}
}
}.start ();
Returnnull;
}
Publicinterfaceimagecallback
{
Publicvoidimageload (IMAGEVIEWIMAGEVIEW,BITMAPBITMAP);
}
}
This is a packaged asynchronous loading picture class, cached two copies, one is cached in memory using soft reference, one is cached to the local SD card, if not in memory, from the local lookup, if not local to get pictures from the network.
Copy Code code as follows:
publicclasshttputils{
Publicstaticinputstreamgetstreamfromurl (Stringimageurl) {
Inputstreamin=null;
try{
Urlurl=newurl (ImageURL);
httpurlconnectionconnection= (HttpURLConnection) url.openconnection ();
In=connection.getinputstream ();
}catch (Exceptione) {
Todoauto-generatedcatchblock
E.printstacktrace ();
}
Returnin;
}
}
This is an access network fetch class. Don't dwell on it.
Let's look at how to use the encapsulated class to load pictures asynchronously:
Copy Code code as follows:
publicclassimagecacheactivityextendsactivity{
/**calledwhentheactivityisfirstcreated.*/
Privatelistviewlistview;
@Override
Publicvoidoncreate (bundlesavedinstancestate) {
Super.oncreate (savedinstancestate);
Setcontentview (R.layout.main);
Listview= (ListView) Findviewbyid (R.id.listview_list);
Myadapteradapter=newmyadapter ();
Listview.setadapter (adapter);
}
privateclassmyadapterextendsbaseadapter{
Privateasyncbitmaploaderasyncbitmaploader;
Publicmyadapter () {
Asyncbitmaploader=newasyncbitmaploader ();
}
@Override
Publicintgetcount () {
Todoauto-generatedmethodstub
RETURN10;
}
@Override
Publicobjectgetitem (intposition) {
Todoauto-generatedmethodstub
Returnnull;
}
@Override
Publiclonggetitemid (intposition) {
Todoauto-generatedmethodstub
Return0;
}
@Override
Publicviewgetview (intposition,viewconvertview,viewgroupparent) {
Todoauto-generatedmethodstub
if (convertview==null) {
Convertview=layoutinflater.from (Getapplicationcontext ()). Inflate (R.layout.list_item,null);
}
Imageviewimage= (ImageView) Convertview.findviewbyid (R.id.addexam_list_icon);
Stringimageurl= "Http://s.ata.net.cn/4f98db46908987a21a000003/logo/2012/04/114_80aaf295c083d07a496743699aac3193.png";
Bitmapbitmap=asyncbitmaploader.loadbitmap (Image,imageurl,newimagecallback () {
@Override
Publicvoidimageload (Imageviewimageview,bitmapbitmap) {
Todoauto-generatedmethodstub
Imageview.setimagebitmap (bitmap);
}
});
if (bitmap==null)
{
Image.setimageresource (R.drawable.ic_launcher);
}
Else
{
Image.setimagebitmap (bitmap);
}
Returnconvertview;
}
}
}
This is done, and the default picture is displayed if the network gets no bitmap.
This is a very practical way, everyone try it yourself!