Google I/O 2013已經(jīng)結(jié)束,它讓我們對(duì)Android將來的發(fā)展有了更大的期待。今年I/O大會(huì)上展示的令人激動(dòng)的創(chuàng)新之一是名為Volley庫(kù)。Volley是一個(gè)處理并緩存網(wǎng)絡(luò)請(qǐng)求的庫(kù),它把開發(fā)者從不同的應(yīng)用中編寫相同代碼的泥潭中拯救出來。編寫相同代碼從來都不是有趣的,還會(huì)增加開發(fā)者的錯(cuò)誤幾率。正式考慮了這一點(diǎn),Google創(chuàng)造了Volley。
如果你沒有看?Google I/O 上介紹Volley的視頻,我建議你先去看一下,在對(duì)它有了基本了解后再繼續(xù)后面的文章。
通過Google I/O介紹,F(xiàn)icus Kirpatrick談?wù)摿嗽S多Volley如何有助于加載圖片的內(nèi)容。當(dāng)使用Volley作為你的圖片加載解決方案時(shí),你會(huì)發(fā)現(xiàn),盡管它自己處理L2緩存,它請(qǐng)求但不包含一個(gè)內(nèi)存不足的L1圖片緩存。很多人已經(jīng)使用過例如Universal Image Loader或Square’s newer Picasso library來處理圖片緩存;然而,這些庫(kù)通常只處理圖片的加載和緩存。那么,我們?nèi)绾问褂肰olley替代它們來加載和緩存圖片呢?首先,讓我們看看Volley提供的加載功能,緩存功能稍后再講。
ImageLoader
ImageLoader類需要一個(gè)請(qǐng)求的實(shí)例以及一個(gè)ImageCache類的實(shí)現(xiàn)。圖片通過傳遞一個(gè)URL和一個(gè)ImageListener實(shí)例到get()方法進(jìn)行加載。從那里,ImageLoader檢查ImageCache,如果圖像不是在緩存中,就從網(wǎng)絡(luò)中加載圖片。
NetworkImageView
這個(gè)類代替布局中的ImageViews類而且使用ImageLoader類。NetworkImageView類的setUrl()方法需要一個(gè)URL路徑字符串和一個(gè)ImageLoader實(shí)例。然后,它使用ImageLoder的get()方法來取回圖片數(shù)據(jù)。
1
2
3
4
5
6
7
8
android:id="@+id/twitterUserImage"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_width="40dp"
android:layout_height="40dp"
android:padding="5dp"
/>
ImageCache
Volley庫(kù)的ImageCache接口允許你使用你喜好的L1緩存實(shí)現(xiàn)。不幸的是,Volley的缺點(diǎn)之一,沒有默認(rèn)的緩存實(shí)現(xiàn)。I/O大會(huì)上演示了一個(gè)BitmapLruCache的代碼片段,但庫(kù)本身沒有包含任何實(shí)現(xiàn)。
ImageCache接口有兩個(gè)方法,getBitmap(String url)和putBitmap(String url, Bitmap bitmap)。這些樁是非常簡(jiǎn)單的,它們可以添加到任何緩存實(shí)現(xiàn)里。
填補(bǔ)空白:向Volley增加一個(gè)圖片緩存
例如,我已經(jīng)創(chuàng)建了一個(gè)簡(jiǎn)單的應(yīng)用,該應(yīng)用通過Twitter搜索”CapTech”,并在一個(gè)列表視圖中顯示搜索到的結(jié)果,每一列包含用戶名和圖片。當(dāng)向下滑動(dòng)時(shí),這個(gè)列表會(huì)自動(dòng)加載舊的記錄,還會(huì)從緩存中獲取圖片。
CapTech
有兩種可用的緩存實(shí)現(xiàn)。推薦的方法是在內(nèi)存中使用一個(gè)基礎(chǔ)的LRU緩存。對(duì)于硬盤的緩存實(shí)現(xiàn),我選擇使用Jack Wharton編寫的DiskLruCache。我選擇這個(gè)實(shí)現(xiàn)是因?yàn)樗贏ndroid社區(qū)中被頻繁的使用,并且有人提供了一個(gè)改造自己的應(yīng)用來適配Volley的用例。使用一個(gè)基于磁盤的L1緩存可能導(dǎo)致阻塞I/O問題。Volley已經(jīng)有一個(gè)隱式的硬盤L2緩存。硬盤L1緩存已經(jīng)被包含在內(nèi)了,因?yàn)槲易畛醪]有察覺Volley如果處理圖片請(qǐng)求緩存。
以下是這個(gè)實(shí)現(xiàn)的主要組件:
RequestManager
RequestManager維護(hù)我們的RequestQueue的一個(gè)引用。Volley使用ResuestQueue來處理我們對(duì)Twitter數(shù)據(jù)和圖片加載的請(qǐng)求。
GsonRequest
GsonRequest與圖片加載沒有直接聯(lián)系,但它代表了如何擴(kuò)展Volley請(qǐng)求類來處理JSON解析。該類用于對(duì)Twitter的GET請(qǐng)求和TwitterData對(duì)象的結(jié)果。
BitmapLruImageCache
該類是一個(gè)基本的“最近最少使用(LRU)”內(nèi)存緩存實(shí)現(xiàn)。它速度快但不會(huì)阻塞I/O。這是推薦的方法。
DiskLruImageCache
DiskLruImageCache是一個(gè)位圖版本的DiskLruCache封裝。它從DiskLruCache中增加并檢索位圖,還處理緩存的實(shí)例化。硬盤緩存可能阻塞I/O。
ImageCacheManager
ImageCacheManager持有ImageCache和Volley ImageLoader引用。
在ImageCacheManager中,你可能注意到一點(diǎn)就是我們使用URL字符串的hashCode()作為緩存的鍵值。這是由于URL中的某些字符不能作為緩存的鍵值。
BuzzArrayAdapter
該適配器比較簡(jiǎn)單的。這里只需要注意一點(diǎn),我們要實(shí)現(xiàn)Volley的Listener和ErrorListener接口,并且把該適配器作為L(zhǎng)istener參數(shù)傳遞給了NetworkImageView 的?setUrl(String string , Listener listener, ErrorListener errorListener)?方法。這個(gè)適配器包含了一些額外代碼用于滾動(dòng)時(shí)加載舊的tweets。
Java
1
2
3
4
5
6
7
8
Tweet tweet = mData.get(position);
if(tweet != null){
viewHolder.twitterUserImage.setImageUrl(tweet.getUserImageUrl(), ImageCacheManager.getInstance().getImageLoader());
viewHolder.userNameTextView.setText("@" + tweet.getUsername());
viewHolder.messageTextView.setText(tweet.getMessage());
viewHolder.tweetTimeTextView.setText(formatDisplayDate(tweet.getCreatedDate()));
viewHolder.destinationUrl = tweet.getDestinationUrl();
}
信息匯總
有了所有這些部分,圖像加載和緩存現(xiàn)在變得非常簡(jiǎn)單。啟動(dòng)時(shí),應(yīng)用程序在MainApplication類中初始化RequestManager和ImageCacheManager類。這里你可以聲明你期望的L1緩存類型。默認(rèn)實(shí)現(xiàn)是內(nèi)存緩存。
在MainActivity中,我們首次調(diào)用TwitterManager并加載初始數(shù)據(jù)。一旦我們接收到返回?cái)?shù)據(jù),我們將它傳遞給BuzzArrayAdapter,并且把BuzzArrayAdapter設(shè)置到ListView中。
在以上的BuzzArrayAdapter代碼中,NetworkImageView承擔(dān)了所有繁重的圖片加載操作,我們只需要將從ImageCacheManager得到的實(shí)例傳達(dá)給圖片加載器就可以了。
ImageCacheManager檢查我們的LRU緩存實(shí)現(xiàn),并返回可用的圖片。如果圖片不在緩存中,它就會(huì)到網(wǎng)絡(luò)中獲取。
當(dāng)你滾動(dòng)ListView時(shí),BuzzArrayAdapter會(huì)加載更多的tweets和相應(yīng)的圖片,并重用已經(jīng)在緩存中的圖片。
結(jié)束時(shí)的思考
盡管Volley是用處大、速度快、容易實(shí)現(xiàn);但現(xiàn)在還不是使用它的時(shí)候,原因如下:
這個(gè)庫(kù)缺少任何說明文檔和使用用例。
例如緩存配置組件,還不具有我期望的高可配置性。
如上所見,排除基本圖片緩存實(shí)現(xiàn)看起來很奇怪。可能包含一個(gè)NoImageCache實(shí)現(xiàn)也許更加有用,或者使緩存變得可配置以滿足只從網(wǎng)絡(luò)上獲取所有信息的需求。
在開發(fā)者社區(qū)有很多與Volley而令人激動(dòng)的消息。給人的感覺是這個(gè)庫(kù)應(yīng)當(dāng)已經(jīng)被作為Android API,并且被引入了很長(zhǎng)時(shí)間了。就像在I/O大會(huì)上宣布的新的Location API 那樣。很顯然,Google正在致力于通過移除一些對(duì)app開發(fā)的阻礙,從而使得開發(fā)者的生活變得更加輕松。
?
評(píng)論