android异步加载图片并缓存到本地实现方法

时间:2022-03-02 15:03:26

在android项目中访问网络图片是非常普遍性的事情,如果我们每次请求都要访问网络来获取图片,会非常耗费流量,而且图片占用内存空间也比较大,图片过多且不释放的话很容易造成内存溢出。针对上面遇到的两个问题,首先耗费流量我们可以将图片第一次加载上面缓存到本地,以后如果本地有就直接从本地加载。图片过多造成内存溢出,这个是最不容易解决的,要想一些好的缓存策略,比如大图片使用lru缓存策略或懒加载缓存策略。今天首先介绍一下本地缓存图片。
首先看一下异步加载缓存本地代码:

复制代码 代码如下:


publicclassasyncbitmaploader
{
/**
*内存图片软引用缓冲
*/
privatehashmap<string,softreference<bitmap>>imagecache=null;
publicasyncbitmaploader()
{
imagecache=newhashmap<string,softreference<bitmap>>();
}
publicbitmaploadbitmap(finalimageviewimageview,finalstringimageurl,finalimagecallbackimagecallback)
{
//在内存缓存中,则返回bitmap对象
if(imagecache.containskey(imageurl))
{
softreference<bitmap>reference=imagecache.get(imageurl);
bitmapbitmap=reference.get();
if(bitmap!=null)
{
returnbitmap;
}
}
else
{
/**
*加上一个对本地缓存的查找
*/
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);
}
};
//如果不在内存缓存中,也不在本地(被jvm回收掉),则开启线程下载图片
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);
}
}


这是一个封装好的异步加载图片类,缓存了两份,一份是使用软引用缓存到内存中,一份是缓存到本地sd卡,如果内存中没有,则从本地查找,如果本地没有则从网络获取图片。

复制代码 代码如下:


publicclasshttputils{
publicstaticinputstreamgetstreamfromurl(stringimageurl){
inputstreamin=null;
try{
urlurl=newurl(imageurl);
httpurlconnectionconnection=(httpurlconnection)url.openconnection();
in=connection.getinputstream();

}catch(exceptione){
//todoauto-generatedcatchblock
e.printstacktrace();
}
returnin;

}
}


这是一个访问网络获取类。不细说了。
下面看一下如何使用封装好的异步加载图片的类:

复制代码 代码如下:


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;
}

}
}


这样就完成了,网络获取不到bitmap则显示默认图片。
android异步加载图片并缓存到本地实现方法 
这是一种很实用的方法,大家自己试试吧!