Android批量图片加载经典系列-采用二级缓存、异步加载网络图片(烟台杰瑞教育Android培训部原创)_第1页
Android批量图片加载经典系列-采用二级缓存、异步加载网络图片(烟台杰瑞教育Android培训部原创)_第2页
Android批量图片加载经典系列-采用二级缓存、异步加载网络图片(烟台杰瑞教育Android培训部原创)_第3页
Android批量图片加载经典系列-采用二级缓存、异步加载网络图片(烟台杰瑞教育Android培训部原创)_第4页
Android批量图片加载经典系列-采用二级缓存、异步加载网络图片(烟台杰瑞教育Android培训部原创)_第5页
已阅读5页,还剩7页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

烟台杰瑞教育科技有限公司(Android开发培训部)版权所有------杰瑞教育()专注IT技能培训打造一流人才服务平台------Android批量图片加载经典系列——采用二级缓存、异步加载网络图片一、问题描述Android应用中经常涉及从网络中加载大量图片,为提升加载速度和效率,减少网络流量都会采用二级缓存和异步加载机制,所谓二级缓存就是通过先从内存中获取、再从文件中获取,最后才会访问网络。内存缓存(一级)本质上是Map集合以key-value对的方式存储图片的url和Bitmap信息,由于内存缓存会造成堆内存泄露,管理相对复杂一些,可采用第三方组件,对于有经验的可自己编写组件,而文件缓存比较简单通常自己封装一下即可。下面就通过案例看如何实现网络图片加载的优化。二、案例介绍案例新闻的列表图片

三、主要核心组件下面先看看实现一级缓存(内存)、二级缓存(磁盘文件)所编写的组件1、MemoryCache在内存中存储图片(一级缓存),采用了1个map来缓存图片代码如下:publicclassMemoryCache{//最大的缓存数privatestaticfinalintMAX_CACHE_CAPACITY=30;//用Map软引用的Bitmap对象,保证内存空间足够情况下不会被垃圾回收privateHashMap<String,SoftReference<Bitmap>>mCacheMap=newLinkedHashMap<String,SoftReference<Bitmap>>(){privatestaticfinallongserialVersionUID=1L;//当缓存数量超过规定大小(返回true)会清除最早放入缓存的protectedbooleanremoveEldestEntry(Map.Entry<String,SoftReference<Bitmap>>eldest){returnsize()>MAX_CACHE_CAPACITY;};};/***从缓存里取出图片*@paramid*@return如果缓存有,并且该图片没被释放,则返回该图片,否则返回null*/publicBitmapget(Stringid){if(!mCacheMap.containsKey(id))returnnull;SoftReference<Bitmap>ref=mCacheMap.get(id);returnref.get();}/***将图片加入缓存*@paramid*@parambitmap*/publicvoidput(Stringid,Bitmapbitmap){mCacheMap.put(id,newSoftReference<Bitmap>(bitmap));}/**mMemoryCache=memoryCache;mFileCache=fileCache;mExecutorService=Executors.newFixedThreadPool(5);//建立一个容量为5的固定尺寸的线程池(最大正在运行的线程数量)}/***根据url加载相应的图片*@paramurl*@return先从一级缓存中取图片有则直接返回,如果没有则异步从文件(二级缓存)中取,如果没有再从网络端获取*/publicBitmaploadBitmap(ImageViewimageView,Stringurl){//先将ImageView记录到Map中,表示该ui已经执行过图片加载了mImageViews.put(imageView,url);Bitmapbitmap=mMemoryCache.get(url);//先从一级缓存中获取图片if(bitmap==null){enquequeLoadPhoto(url,imageView);//再从二级缓存和网络中获取}returnbitmap;}/***加入图片下载队列*@paramurl*/privatevoidenquequeLoadPhoto(Stringurl,ImageViewimageView){//如果任务已经存在,则不重新添加if(isTaskExisted(url))return;LoadPhotoTasktask=newLoadPhotoTask(url,imageView);synchronized(mTaskQueue){mTaskQueue.add(task);//将任务添加到队列中}mExecutorService.execute(task);//向线程池中提交任务,如果没有达到上限(5),则运行否则被阻塞}/***判断下载队列中是否已经存在该任务*@paramurl*@return*/privatebooleanisTaskExisted(Stringurl){if(url==null)returnfalse;synchronized(mTaskQueue){intsize=mTaskQueue.size();for(inti=0;i<size;i++){LoadPhotoTasktask=mTaskQueue.get(i);if(task!=null&&task.getUrl().equals(url))returntrue;}}returnfalse;}/***从缓存文件或者网络端获取图片*@paramurl*/privateBitmapgetBitmapByUrl(Stringurl){Filef=mFileCache.getFile(url);//获得缓存图片路径Bitmapb=ImageUtil.decodeFile(f);//获得文件的Bitmap信息if(b!=null)//不为空表示获得了缓存的文件returnb;returnImageUtil.loadBitmapFromWeb(url,f);//同网络获得图片}/***判断该ImageView是否已经加载过图片了(可用于判断是否需要进行加载图片)*@paramimageView*@paramurl*@return*/privatebooleanimageViewReused(ImageViewimageView,Stringurl){Stringtag=mImageViews.get(imageView);if(tag==null||!tag.equals(url))returntrue;returnfalse;}privatevoidremoveTask(LoadPhotoTasktask){synchronized(mTaskQueue){mTaskQueue.remove(task);}}classLoadPhotoTaskimplementsRunnable{privateStringurl;privateImageViewimageView;LoadPhotoTask(Stringurl,ImageViewimageView){this.url=url;this.imageView=imageView;}@Overridepublicvoidrun(){if(imageViewReused(imageView,url)){//判断ImageView是否已经被复用removeTask(this);//如果已经被复用则删除任务return;}Bitmapbmp=getBitmapByUrl(url);//从缓存文件或者网络端获取图片mMemoryCache.put(url,bmp);//将图片放入到一级缓存中if(!imageViewReused(imageView,url)){//若ImageView未加图片则在ui线程中显示图片BitmapDisplayerbd=newBitmapDisplayer(bmp,imageView,url);Activitya=(Activity)imageView.getContext();a.runOnUiThread(bd);//在UI线程调用bd组件的run方法,实现为ImageView控件加载图片}removeTask(this);//从队列中移除任务}publicStringgetUrl(){returnurl;}}/****由UI线程中执行该组件的run方法*/classBitmapDisplayerimplementsRunnable{privateBitmapbitmap;privateImageViewimageView;privateStringurl;publicBitmapDisplayer(Bitmapb,ImageViewimageView,Stringurl){bitmap=b;this.imageView=imageView;this.url=url;}publicvoidrun(){if(imageViewReused(imageView,url))return;if(bitmap!=null)imageView.setImageBitmap(bitmap);}}/***释放资源*/publicvoiddestroy(){mMemoryCache.clear();mMemoryCache=null;mImageViews.clear();mImageViews=null;mTaskQueue.clear();mTaskQueue=null;mExecutorService.shutdown();mExecutorService=null;}}编写完成之后,对于异步任务的执行只需调用AsyncImageLoader中的loadBitmap()方法即可非常方便,对于AsyncImageLoader组件的代码最好结合注释好好理解一下,这样对于Android中线程之间的异步通信就会有深刻的认识。4、工具类ImageUtilpublicclassImageUtil{/***从网络获取图片,并缓存在指定的文件中*@paramurl图片url*@paramfile缓存文件*@return*/publicstaticBitmaploadBitmapFromWeb(Stringurl,Filefile){HttpURLConnectionconn=null;InputStreamis=null;OutputStreamos=null;try{Bitmapbitmap=null;URLimageUrl=newURL(url);conn=(HttpURLConnection)imageUrl.openConnection();conn.setConnectTimeout(30000);conn.setReadTimeout(30000);conn.setInstanceFollowRedirects(true);is=conn.getInputStream();os=newFileOutputStream(file);copyStream(is,os);//将图片缓存到磁盘中bitmap=decodeFile(file);returnbitmap;}catch(Exceptionex){ex.printStackTrace();returnnull;}finally{try{if(os!=null)os.close();if(is!=null)is.close();if(conn!=null)conn.disconnect();}catch(IOExceptione){}}}publicstaticBitmapdecodeFile(Filef){try{returnBitmapFactory.decodeStream(newFileInputStream(f),null,null);}catch(Exceptione){}returnnull;}privatestaticvoidcopyStream(InputStreamis,OutputStreamos){finalintbuffer_size=1024;try{byte[]bytes=newbyte[buffer_size];for(;;){intcount=is.read(bytes,0,buffer_size);if(count==-1)break;os.write(bytes,0,count);}}catch(Exceptionex){ex.printStackTrace();}}}四、测试应用

组件之间的时序图:1、编写MainActivitypublicclassMainActivityextendsActivity{ListViewlist;ListViewAdapteradapter;@OverridepublicvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.main);list=(ListView)findViewById(R.id.list);adapter=newListViewAdapter(this,mStrings);list.setAdapter(adapter);}publicvoidonDestroy(){list.setAdapter(null);super.onDestroy();adapter.destroy();}privateString[]mStrings={"/UserFiles/x_Image/x_20150606083511_0.jpg","/UserFiles/x_Image/x_20150606082847_0.jpg",…..};}2、编写适配器publicclassListViewAdapterextendsBaseAdapter{privateActivitymActivity;privateString[]data;privatestaticLayoutInflaterinflater=null;privateAsyncImageLoaderimageLoader;//异步组件publicListViewAdapter(ActivitymActivity,String[]d){this.mActivity=mActivity;data=d;inflater=(LayoutInflater)mActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);MemoryCachemcache=newMemoryCache();//内存缓存FilesdCard=android.os.Environment.getExternalStorageDirectory();//获得SD卡FilecacheDir=newFile(sdCard,"jereh_cache");//缓存根目录FileCachefcache=newFileCache(mActivity,cacheDir,"news_img");//文件缓存imageLoader=newAsyncImageLoader(mActivity,mcache,fcache);}publicintgetCount(){returndata.length;}publicObjectgetItem(intposition){returnposition;}publiclonggetItemId(intposition){returnposition;

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论