Listview异步加载之优化篇异步加载图片基本思想:1.先从内存缓存中获取图片显示(内存缓冲)2.获取不到的话从SD卡里获取(SD卡缓冲)3.都获取不到的话从网络下载图片并保存到SD卡同时加入内存并显示(视情况看是否要显示)1.publicclassLoaderAdapterextendsBaseAdapter{2.3.privatestaticfinalStringTAG=LoaderAdapter;4.privatebooleanmBusy=false;5.6.publicvoidsetFlagBusy(booleanbusy){7.this.mBusy=busy;8.}9.10.11.privateImageLoadermImageLoader;12.privateintmCount;13.privateContextmContext;14.privateString[]urlArrays;15.16.17.publicLoaderAdapter(intcount,Contextcontext,String[]url){18.this.mCount=count;19.this.mContext=context;20.urlArrays=url;21.mImageLoader=newImageLoader(context);22.}23.24.publicImageLoadergetImageLoader(){25.returnmImageLoader;26.}27.28.@Override29.publicintgetCount(){30.returnmCount;31.}32.33.@Override34.publicObjectgetItem(intposition){35.returnposition;36.}37.38.@Override39.publiclonggetItemId(intposition){40.returnposition;41.}42.43.@Override44.publicViewgetView(intposition,ViewconvertView,ViewGroupparent){45.46.ViewHolderviewHolder=null;47.if(convertView==null){48.convertView=LayoutInflater.from(mContext).inflate(49.R.layout.list_item,null);50.viewHolder=newViewHolder();51.viewHolder.mTextView=(TextView)convertView52..findViewById(R.id.tv_tips);53.viewHolder.mImageView=(ImageView)convertView54..findViewById(R.id.iv_image);55.convertView.setTag(viewHolder);56.}else{57.viewHolder=(ViewHolder)convertView.getTag();58.}59.Stringurl=;60.url=urlArrays[position%urlArrays.length];61.62.viewHolder.mImageView.setImageResource(R.drawable.ic_launcher);63.64.65.if(!mBusy){66.mImageLoader.DisplayImage(url,viewHolder.mImageView,false);67.viewHolder.mTextView.setText(--+position68.+--IDLE||TOUCH_SCROLL);69.}else{70.mImageLoader.DisplayImage(url,viewHolder.mImageView,true);71.viewHolder.mTextView.setText(--+position+--FLING);72.}73.returnconvertView;74.}75.76.staticclassViewHolder{77.TextViewmTextView;78.ImageViewmImageView;79.}80.}关键代码是ImageLoader的DisplayImage方法,再看ImageLoader的实现[java]viewplaincopyprint?1.publicclassImageLoader{2.3.privateMemoryCachememoryCache=newMemoryCache();4.privateAbstractFileCachefileCache;5.privateMapImageView,StringimageViews=Collections6..synchronizedMap(newWeakHashMapImageView,String());7.//线程池8.privateExecutorServiceexecutorService;9.10.publicImageLoader(Contextcontext){11.fileCache=newFileCache(context);12.executorService=Executors.newFixedThreadPool(5);13.}14.15.//最主要的方法16.publicvoidDisplayImage(Stringurl,ImageViewimageView,booleanisLoadOnlyFromCache){17.imageViews.put(imageView,url);18.//先从内存缓存中查找19.20.Bitmapbitmap=memoryCache.get(url);21.if(bitmap!=null)22.imageView.setImageBitmap(bitmap);23.elseif(!isLoadOnlyFromCache){24.25.//若没有的话则开启新线程加载图片26.queuePhoto(url,imageView);27.}28.}29.30.privatevoidqueuePhoto(Stringurl,ImageViewimageView){31.PhotoToLoadp=newPhotoToLoad(url,imageView);32.executorService.submit(newPhotosLoader(p));33.}34.35.privateBitmapgetBitmap(Stringurl){36.Filef=fileCache.getFile(url);37.38.//先从文件缓存中查找是否有39.Bitmapb=null;40.if(f!=null&&f.exists()){41.b=decodeFile(f);42.}43.if(b!=null){44.returnb;45.}46.//最后从指定的url中下载图片47.try{48.Bitmapbitmap=null;49.URLimageUrl=newURL(url);50.HttpURLConnectionconn=(HttpURLConnection)imageUrl51..openConnection();52.conn.setConnectTimeout(30000);53.conn.setReadTimeout(30000);54.conn.setInstanceFollowRedirects(true);55.InputStreamis=conn.getInputStream();56.OutputStreamos=newFileOutputStream(f);57.CopyStream(is,os);58.os.close();59.bitmap=decodeFile(f);60.returnbitmap;61.}catch(Exceptionex){62.Log.e(,getBitmapcatchException...\nmessage=+ex.getMessage());63.returnnull;64.}65.}66.67.//decode这个图片并且按比例缩放以减少内存消耗,虚拟机对每张图片的缓存大小也是有限制的68.privateBitmapdecodeFile(Filef){69.try{70.//decodeimagesize71.BitmapFactory.Optionso=newBitmapFactory.Options();72.o.inJustDecodeBounds=true;73.BitmapFactory.decodeStream(newFileInputStream(f),null,o);74.75.//Findthecorrectscalevalue.Itshouldbethepowerof2.76.finalintREQUIRED_SIZE=100;77.intwidth_tmp=o.outWidth,height_tmp=o.outHeight;78.intscale=1;79.while(true){80.if(width_tmp/2REQUIRED_SIZE81.||height_tmp/2REQUIRED_SIZE)82.break;83.width_tmp/=2;84.height_tmp/=2;85.scale*=2;86.}87.88.//decodewithinSampleSize89.BitmapFactory.Optionso2=newBitmapFactory.Options();90.o2.inSampleSize=scale;91.returnBitmapFactory.decodeStream(newFileInputStream(f),null,o2);92.}catch(FileNotFoundExceptione){93.}94.returnnull;95.}96.97.//Taskforthequeue98.privateclassPhotoToLoad{99.publicStringurl;100.publicImageViewimageView;101.102.publicPhotoToLoad(Stringu,ImageViewi){103.url=u;104.imageView=i;105.}106.}107.108.classPhotosLoaderimplementsRunnable{109.PhotoToLoadphotoToLoad;110.111.PhotosLoader(PhotoToLoadphotoToLoad){112.this.photoToLoad=photoToLoad;113.}114.115.@Override116.publicvoidrun(){117.if(imageViewReused(photoToLoad))118.return;119.Bitmapbmp=getBitmap(photoToLoad.url);120.memoryCache.put(photoToLoad.url,bmp);121.if(imageViewReused(photoToLoad))122.return;123.BitmapDisplayerbd=newBitmapDisplayer(bmp,photoToLoad);124.//更新的操作放在UI线程中125.Activitya=(Activity)photoToLoad.imageView.getContext();126.a.runOnUiThread(bd);127.}128.}1