這里不貼大段的代碼了荔泳,單單列出思路,和一些解決思路虐杯。
我們的圖片加載過(guò)程玛歌,可以引入緩存,我們?cè)O(shè)計(jì)一種兩層緩存的架構(gòu)擎椰,當(dāng)拿到一個(gè)需要加載的圖片的url時(shí)支子,我們先從內(nèi)存緩存中根據(jù)url查找看內(nèi)存緩存有沒(méi)有相關(guān)緩存,如果沒(méi)有达舒,那么我們?cè)诖疟P(pán)緩存中進(jìn)行查找值朋,如果磁盤(pán)緩存也沒(méi)有,那么我們需要發(fā)出真正的網(wǎng)絡(luò)請(qǐng)求巩搏,進(jìn)行圖片的加載昨登,當(dāng)圖片網(wǎng)絡(luò)加載成功時(shí)將圖片存入兩級(jí)緩存。
內(nèi)存緩存的實(shí)現(xiàn)贯底,可以借助LruCache篙骡,大小可以指定為app可用內(nèi)存的8分之一。
磁盤(pán)緩存可以借助DiskLruCache,也可以自己在app的緩存目錄下進(jìn)行文件io糯俗,注意由于文件Io比較慢尿褪,因此存和取最好都要開(kāi)啟新的異步任務(wù)。另外如果自己進(jìn)行實(shí)現(xiàn)得湘,可以考慮對(duì)url進(jìn)行MD5運(yùn)算杖玲,將文件名取為hash值,同時(shí)使用app緩存文件時(shí)淘正,最好自己在建一個(gè)子目錄摆马。另外app內(nèi)部可以有一個(gè)菜單展示當(dāng)前磁盤(pán)緩存大小,方便進(jìn)行清理鸿吆。
網(wǎng)絡(luò)請(qǐng)求的實(shí)現(xiàn)囤采,最基本的要通過(guò)異步任務(wù)來(lái)獲取圖片。
加載圖片的優(yōu)化問(wèn)題惩淳。
圖片是各式各樣的蕉毯,大多數(shù)情況下,我們要展示的圖片思犁,比原始圖片小很多代虾。比如用戶頭像控件只有6464,如果用戶的頭像的原始文件有512512,那么即使我們加載了原始圖片,然而肉眼也看不出區(qū)別缤剧。因此,我們加載圖片的時(shí)候乘瓤,可以先獲取即將加載的圖片的大小,格式等策泣,然后根據(jù)需要的尺寸衙傀,加載重新采樣的版本。這一個(gè)過(guò)程着降,對(duì)于網(wǎng)絡(luò)加載同樣適用差油。BitmapFactory的decodeStream可以從網(wǎng)絡(luò)輸入流加載圖片拗军。不過(guò)如果我們先測(cè)量任洞,后加載,可能會(huì)爆io異常发侵,這是由于同一個(gè)輸入流被讀取了兩次交掏。根據(jù)api,第一次測(cè)量的時(shí)候刃鳄,輸入流的讀取位置被改變了盅弛,如果需要再次讀取,需要先復(fù)位。然而我測(cè)試發(fā)現(xiàn)挪鹏,即使復(fù)位见秽,也有可能報(bào)異常,因此參考了網(wǎng)絡(luò)的其它回答讨盒。我們可以將輸入流數(shù)據(jù)寫(xiě)入字節(jié)數(shù)組輸出流中解取,然后就可以多次對(duì)流進(jìn)行操作了。
網(wǎng)絡(luò)請(qǐng)求的發(fā)出優(yōu)化
當(dāng)需要加載大量圖片時(shí)返顺,可能會(huì)有這樣的場(chǎng)景禀苦,即當(dāng)前頁(yè)面的圖片還沒(méi)有加載出來(lái),我們已經(jīng)滑動(dòng)到了其它頁(yè)面遂鹊,或者下一頁(yè)振乏,這導(dǎo)致發(fā)出的網(wǎng)絡(luò)請(qǐng)求越來(lái)越多,而用戶目前正在查看的內(nèi)容的網(wǎng)絡(luò)請(qǐng)求無(wú)法最快完成秉扑。比如在一個(gè)展示圖片的app中慧邮,上拉會(huì)加載更多圖片。如果在當(dāng)前頁(yè)的圖片未完全展示的情況下邻储,用戶進(jìn)行了多次上拉操作赋咽,那么即使一開(kāi)始的頁(yè)面的圖片已經(jīng)沒(méi)用了,后臺(tái)的網(wǎng)絡(luò)請(qǐng)求還是回去先加載它們吨娜,從而使得當(dāng)前用戶停留頁(yè)面的圖片得不到即使加載脓匿。
我在實(shí)現(xiàn)中曾引入一個(gè)簡(jiǎn)單的設(shè)計(jì),一個(gè)存儲(chǔ)異步任務(wù)的數(shù)組宦赠,發(fā)出任務(wù)時(shí)陪毡,加入數(shù)組,如果超過(guò)一定的閾值勾扭,那么就取消最先加入的任務(wù)毡琉,而添加新的任務(wù)。