Android批量圖片加載經(jīng)典系列-采用二級緩存、異步加載網(wǎng)絡(luò)圖片(煙臺杰瑞教育Android培訓(xùn)部原創(chuàng))_第1頁
Android批量圖片加載經(jīng)典系列-采用二級緩存、異步加載網(wǎng)絡(luò)圖片(煙臺杰瑞教育Android培訓(xùn)部原創(chuàng))_第2頁
Android批量圖片加載經(jīng)典系列-采用二級緩存、異步加載網(wǎng)絡(luò)圖片(煙臺杰瑞教育Android培訓(xùn)部原創(chuàng))_第3頁
Android批量圖片加載經(jīng)典系列-采用二級緩存、異步加載網(wǎng)絡(luò)圖片(煙臺杰瑞教育Android培訓(xùn)部原創(chuàng))_第4頁
Android批量圖片加載經(jīng)典系列-采用二級緩存、異步加載網(wǎng)絡(luò)圖片(煙臺杰瑞教育Android培訓(xùn)部原創(chuàng))_第5頁
已閱讀5頁,還剩7頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

煙臺杰瑞教育科技有限公司(Android開發(fā)培訓(xùn)部)版權(quán)所有------杰瑞教育()專注IT技能培訓(xùn)打造一流人才服務(wù)平臺------Android批量圖片加載經(jīng)典系列——采用二級緩存、異步加載網(wǎng)絡(luò)圖片一、問題描述Android應(yīng)用中經(jīng)常涉及從網(wǎng)絡(luò)中加載大量圖片,為提升加載速度和效率,減少網(wǎng)絡(luò)流量都會采用二級緩存和異步加載機(jī)制,所謂二級緩存就是通過先從內(nèi)存中獲取、再從文件中獲取,最后才會訪問網(wǎng)絡(luò)。內(nèi)存緩存(一級)本質(zhì)上是Map集合以key-value對的方式存儲圖片的url和Bitmap信息,由于內(nèi)存緩存會造成堆內(nèi)存泄露,管理相對復(fù)雜一些,可采用第三方組件,對于有經(jīng)驗(yàn)的可自己編寫組件,而文件緩存比較簡單通常自己封裝一下即可。下面就通過案例看如何實(shí)現(xiàn)網(wǎng)絡(luò)圖片加載的優(yōu)化。二、案例介紹案例新聞的列表圖片

三、主要核心組件下面先看看實(shí)現(xiàn)一級緩存(內(nèi)存)、二級緩存(磁盤文件)所編寫的組件1、MemoryCache在內(nèi)存中存儲圖片(一級緩存),采用了1個(gè)map來緩存圖片代碼如下:publicclassMemoryCache{//最大的緩存數(shù)privatestaticfinalintMAX_CACHE_CAPACITY=30;//用Map軟引用的Bitmap對象,保證內(nèi)存空間足夠情況下不會被垃圾回收privateHashMap<String,SoftReference<Bitmap>>mCacheMap=newLinkedHashMap<String,SoftReference<Bitmap>>(){privatestaticfinallongserialVersionUID=1L;//當(dāng)緩存數(shù)量超過規(guī)定大小(返回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);//建立一個(gè)容量為5的固定尺寸的線程池(最大正在運(yùn)行的線程數(shù)量)}/***根據(jù)url加載相應(yīng)的圖片*@paramurl*@return先從一級緩存中取圖片有則直接返回,如果沒有則異步從文件(二級緩存)中取,如果沒有再從網(wǎng)絡(luò)端獲取*/publicBitmaploadBitmap(ImageViewimageView,Stringurl){//先將ImageView記錄到Map中,表示該ui已經(jīng)執(zhí)行過圖片加載了mImageViews.put(imageView,url);Bitmapbitmap=mMemoryCache.get(url);//先從一級緩存中獲取圖片if(bitmap==null){enquequeLoadPhoto(url,imageView);//再從二級緩存和網(wǎng)絡(luò)中獲取}returnbitmap;}/***加入圖片下載隊(duì)列*@paramurl*/privatevoidenquequeLoadPhoto(Stringurl,ImageViewimageView){//如果任務(wù)已經(jīng)存在,則不重新添加if(isTaskExisted(url))return;LoadPhotoTasktask=newLoadPhotoTask(url,imageView);synchronized(mTaskQueue){mTaskQueue.add(task);//將任務(wù)添加到隊(duì)列中}mExecutorService.execute(task);//向線程池中提交任務(wù),如果沒有達(dá)到上限(5),則運(yùn)行否則被阻塞}/***判斷下載隊(duì)列中是否已經(jīng)存在該任務(wù)*@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;}/***從緩存文件或者網(wǎng)絡(luò)端獲取圖片*@paramurl*/privateBitmapgetBitmapByUrl(Stringurl){Filef=mFileCache.getFile(url);//獲得緩存圖片路徑Bitmapb=ImageUtil.decodeFile(f);//獲得文件的Bitmap信息if(b!=null)//不為空表示獲得了緩存的文件returnb;returnImageUtil.loadBitmapFromWeb(url,f);//同網(wǎng)絡(luò)獲得圖片}/***判斷該ImageView是否已經(jīng)加載過圖片了(可用于判斷是否需要進(jìn)行加載圖片)*@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是否已經(jīng)被復(fù)用removeTask(this);//如果已經(jīng)被復(fù)用則刪除任務(wù)return;}Bitmapbmp=getBitmapByUrl(url);//從緩存文件或者網(wǎng)絡(luò)端獲取圖片mMemoryCache.put(url,bmp);//將圖片放入到一級緩存中if(!imageViewReused(imageView,url)){//若ImageView未加圖片則在ui線程中顯示圖片BitmapDisplayerbd=newBitmapDisplayer(bmp,imageView,url);Activitya=(Activity)imageView.getContext();a.runOnUiThread(bd);//在UI線程調(diào)用bd組件的run方法,實(shí)現(xiàn)為ImageView控件加載圖片}removeTask(this);//從隊(duì)列中移除任務(wù)}publicStringgetUrl(){returnurl;}}/****由UI線程中執(zhí)行該組件的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;}}編寫完成之后,對于異步任務(wù)的執(zhí)行只需調(diào)用AsyncImageLoader中的loadBitmap()方法即可非常方便,對于AsyncImageLoader組件的代碼最好結(jié)合注釋好好理解一下,這樣對于Android中線程之間的異步通信就會有深刻的認(rèn)識。4、工具類ImageUtilpublicclassImageUtil{/***從網(wǎng)絡(luò)獲取圖片,并緩存在指定的文件中*@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();}}}四、測試應(yīng)用

組件之間的時(shí)序圖: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();//內(nèi)存緩存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. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論