Android实现图片异步加载并缓存到本地
在android应用开发的时候,加载网络图片是一个非常重要的部分,很多图片不可能放在本地,所以就必须要从服务器或者网络读取图片。
软引用是一个现在非常流行的方法,用户体验比较好,不用每次都需要从网络下载图片,如果下载后就存到本地,下次读取时首先查看本地有没有,如果没有再从网络读取。
下面就分享一下异步加载网络图片的方法吧。
FileCache.java
importjava.io.File; importandroid.content.Context; publicclassFileCache{ privateFilecacheDir; publicFileCache(Contextcontext){ //找一个用来缓存图片的路径 if(android.os.Environment.getExternalStorageState().equals( android.os.Environment.MEDIA_MOUNTED)) cacheDir=newFile(android.os.Environment.getExternalStorageDirectory(), "文件夹名称"); else cacheDir=context.getCacheDir(); if(!cacheDir.exists()) cacheDir.mkdirs(); } publicFilegetFile(Stringurl){ Stringfilename=String.valueOf(url.hashCode()); Filef=newFile(cacheDir,filename); returnf; } publicvoidclear(){ File[]files=cacheDir.listFiles(); if(files==null) return; for(Filef:files) f.delete(); } }
HttpUtil.java
importjava.io.ByteArrayOutputStream; importjava.io.File; importjava.io.FileNotFoundException; importjava.io.FileOutputStream; importjava.io.IOException; importjava.io.InputStream; importjava.io.OutputStream; importjava.io.UnsupportedEncodingException; importjava.net.HttpURLConnection; importjava.net.MalformedURLException; importjava.net.ProtocolException; importjava.net.URL; importjava.net.URLEncoder; importjava.util.Map; /** *Http请求工具类 * *@authorScorpio.Liu * */ publicclassHttpUtil{ /** *获取响应字符串 * *@parampath *路径 *@paramparameters *参数 *@return响应字符串 */ publicstaticStringgetResponseStr(Stringpath,Map<String,String>parameters){ StringBufferbuffer=newStringBuffer(); URLurl; try{ if(parameters!=null&&!parameters.isEmpty()){ for(Map.Entry<String,String>entry:parameters.entrySet()){ //完成转码操作 buffer.append(entry.getKey()).append("=") .append(URLEncoder.encode(entry.getValue(),"UTF-8")).append("&"); } buffer.deleteCharAt(buffer.length()-1); } url=newURL(path); HttpURLConnectionurlConnection=(HttpURLConnection)url.openConnection(); urlConnection.setConnectTimeout(3000); urlConnection.setRequestMethod("POST"); urlConnection.setDoInput(true);//表示从服务器获取数据 urlConnection.setDoOutput(true);//表示向服务器写数据 //获得上传信息的字节大小以及长度 byte[]mydata=buffer.toString().getBytes(); //表示设置请求体的类型是文本类型 urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); urlConnection.setRequestProperty("Content-Length",String.valueOf(mydata.length)); //获得输出流,向服务器输出数据 OutputStreamoutputStream=urlConnection.getOutputStream(); outputStream.write(mydata,0,mydata.length); outputStream.close(); intresponseCode=urlConnection.getResponseCode(); if(responseCode==200){ returnchangeInputStream(urlConnection.getInputStream()); } }catch(UnsupportedEncodingExceptione){ e.printStackTrace(); }catch(MalformedURLExceptione){ e.printStackTrace(); }catch(ProtocolExceptione){ e.printStackTrace(); }catch(IOExceptione){ e.printStackTrace(); } returnnull; } privatestaticStringchangeInputStream(InputStreaminputStream){ ByteArrayOutputStreamoutputStream=newByteArrayOutputStream(); byte[]data=newbyte[1024]; intlen=0; Stringresult=""; if(inputStream!=null){ try{ while((len=inputStream.read(data))!=-1){ outputStream.write(data,0,len); } result=newString(outputStream.toByteArray(),"UTF-8"); }catch(IOExceptione){ e.printStackTrace(); } } returnresult; } publicstaticInputStreamgetInputStream(Stringpath){ URLurl; try{ url=newURL(path); HttpURLConnectionurlConnection=(HttpURLConnection)url.openConnection(); urlConnection.setConnectTimeout(3000); urlConnection.setRequestMethod("GET"); urlConnection.setDoInput(true);//表示从服务器获取数据 urlConnection.connect(); if(urlConnection.getResponseCode()==200) returnurlConnection.getInputStream(); }catch(MalformedURLExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); }catch(IOExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); }catch(Exceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); } returnnull; } publicstaticbyte[]readStream(InputStreaminStream)throwsException{ ByteArrayOutputStreamoutSteam=newByteArrayOutputStream(); byte[]buffer=newbyte[1024]; intlen=-1; while((len=inStream.read(buffer))!=-1){ outSteam.write(buffer,0,len); } outSteam.close(); inStream.close(); returnoutSteam.toByteArray(); } publicstaticvoidCopyStream(Stringurl,Filef){ FileOutputStreamfileOutputStream=null; InputStreaminputStream=null; try{ inputStream=getInputStream(url); byte[]data=newbyte[1024]; intlen=0; fileOutputStream=newFileOutputStream(f); while((len=inputStream.read(data))!=-1){ fileOutputStream.write(data,0,len); } }catch(FileNotFoundExceptione){ e.printStackTrace(); }catch(IOExceptione){ e.printStackTrace(); }finally{ if(inputStream!=null){ try{ inputStream.close(); }catch(IOExceptione){ e.printStackTrace(); } } if(fileOutputStream!=null){ try{ fileOutputStream.close(); }catch(IOExceptione){ e.printStackTrace(); } } } } }
MemoryCache.java
importjava.lang.ref.SoftReference; importjava.util.Collections; importjava.util.HashMap; importjava.util.Map; importandroid.graphics.Bitmap; publicclassMemoryCache{ privateMap<String,SoftReference<Bitmap>>cache=Collections .synchronizedMap(newHashMap<String,SoftReference<Bitmap>>());//软引用 publicBitmapget(Stringid){ if(!cache.containsKey(id)) returnnull; SoftReference<Bitmap>ref=cache.get(id); returnref.get(); } publicvoidput(Stringid,Bitmapbitmap){ cache.put(id,newSoftReference<Bitmap>(bitmap)); } publicvoidclear(){ cache.clear(); } }
ImageLoader.java
importjava.io.File; importjava.io.FileInputStream; importjava.io.FileNotFoundException; importjava.io.UnsupportedEncodingException; importjava.net.URLEncoder; importjava.util.Collections; importjava.util.Map; importjava.util.WeakHashMap; importjava.util.concurrent.ExecutorService; importjava.util.concurrent.Executors; importandroid.app.Activity; importandroid.content.Context; importandroid.graphics.Bitmap; importandroid.graphics.BitmapFactory; importandroid.graphics.drawable.BitmapDrawable; importandroid.widget.ImageView; publicclassImageLoader{ privateMemoryCachememoryCache=newMemoryCache(); privateFileCachefileCache; privateMap<ImageView,String>imageViews=Collections .synchronizedMap(newWeakHashMap<ImageView,String>()); privateExecutorServiceexecutorService; privatebooleanisSrc; /** *@paramcontext *上下文对象 *@paramflag *true为source资源,false为background资源 */ publicImageLoader(Contextcontext,booleanflag){ fileCache=newFileCache(context); executorService=Executors.newFixedThreadPool(5); isSrc=flag; } finalintstub_id=R.drawable.ic_launcher; publicvoidDisplayImage(Stringurl,ImageViewimageView){ Stringu1=url.substring(0,url.lastIndexOf("/")+1); Stringu2=url.substring(url.lastIndexOf("/")+1); try{ u2=URLEncoder.encode(u2,"UTF-8"); }catch(UnsupportedEncodingExceptione){ e.printStackTrace(); } url=u1+u2; imageViews.put(imageView,url); Bitmapbitmap=memoryCache.get(url); if(bitmap!=null){ if(isSrc) imageView.setImageBitmap(bitmap); else imageView.setBackgroundDrawable(newBitmapDrawable(bitmap)); }else{ queuePhoto(url,imageView); if(isSrc) imageView.setImageResource(stub_id); else imageView.setBackgroundResource(stub_id); } } privatevoidqueuePhoto(Stringurl,ImageViewimageView){ PhotoToLoadp=newPhotoToLoad(url,imageView); executorService.submit(newPhotosLoader(p)); } privateBitmapgetBitmap(Stringurl){ try{ Filef=fileCache.getFile(url); //从sd卡 Bitmapb=onDecodeFile(f); if(b!=null) returnb; //从网络 Bitmapbitmap=null; System.out.println("ImageLoader-->download"); HttpUtil.CopyStream(url,f); bitmap=onDecodeFile(f); returnbitmap; }catch(Exceptionex){ ex.printStackTrace(); returnnull; } } publicBitmaponDecodeFile(Filef){ try{ returnBitmapFactory.decodeStream(newFileInputStream(f)); }catch(FileNotFoundExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); } returnnull; } /** *解码图像用来减少内存消耗 * *@paramf *@return */ publicBitmapdecodeFile(Filef){ try{ //解码图像大小 BitmapFactory.Optionso=newBitmapFactory.Options(); o.inJustDecodeBounds=true; BitmapFactory.decodeStream(newFileInputStream(f),null,o); //找到正确的刻度值,它应该是2的幂。 finalintREQUIRED_SIZE=70; intwidth_tmp=o.outWidth,height_tmp=o.outHeight; intscale=1; while(true){ if(width_tmp/2<REQUIRED_SIZE||height_tmp/2<REQUIRED_SIZE) break; width_tmp/=2; height_tmp/=2; scale*=2; } BitmapFactory.Optionso2=newBitmapFactory.Options(); o2.inSampleSize=scale; returnBitmapFactory.decodeStream(newFileInputStream(f),null,o2); }catch(FileNotFoundExceptione){ } returnnull; } /** *任务队列 * *@authorScorpio.Liu * */ privateclassPhotoToLoad{ publicStringurl; publicImageViewimageView; publicPhotoToLoad(Stringu,ImageViewi){ url=u; imageView=i; } } classPhotosLoaderimplementsRunnable{ PhotoToLoadphotoToLoad; PhotosLoader(PhotoToLoadphotoToLoad){ this.photoToLoad=photoToLoad; } @Override publicvoidrun(){ if(imageViewReused(photoToLoad)) return; Bitmapbmp=getBitmap(photoToLoad.url); memoryCache.put(photoToLoad.url,bmp); if(imageViewReused(photoToLoad)) return; BitmapDisplayerbd=newBitmapDisplayer(bmp,photoToLoad); Activitya=(Activity)photoToLoad.imageView.getContext(); a.runOnUiThread(bd); } } booleanimageViewReused(PhotoToLoadphotoToLoad){ Stringtag=imageViews.get(photoToLoad.imageView); if(tag==null||!tag.equals(photoToLoad.url)) returntrue; returnfalse; } /** *显示位图在UI线程 * *@authorScorpio.Liu * */ classBitmapDisplayerimplementsRunnable{ Bitmapbitmap; PhotoToLoadphotoToLoad; publicBitmapDisplayer(Bitmapb,PhotoToLoadp){ bitmap=b; photoToLoad=p; } publicvoidrun(){ if(imageViewReused(photoToLoad)) return; if(bitmap!=null){ if(isSrc) photoToLoad.imageView.setImageBitmap(bitmap); else photoToLoad.imageView.setBackgroundDrawable(newBitmapDrawable(bitmap)); }else{ if(isSrc) photoToLoad.imageView.setImageResource(stub_id); else photoToLoad.imageView.setBackgroundResource(stub_id); } } } publicvoidclearCache(){ memoryCache.clear(); fileCache.clear(); } }
使用的时候用ImageLoader这个类就ok了,很方便~
希望本文所述对大家学习Android软件编程有所帮助。