搜芽的移動開發這幾天進度相對來說非常的快。但是美中不足的就是網絡圖片的加載問題。我有兩套方案:
1)沿用迅雷動漫的圖片加載。迅雷動漫也是用的一個開源的庫。但是不知道是我使用出了問題還是真的是它的問題。在我迅速的下拉和回倒的時候,
不確定的會出現崩潰。logcat顯示loadImage裡面出現了內存溢出.out of memory.。這個我想應該不是我的問題。
2)采用外包的AsyncImageLoader。這個文件我沒有仔細看。然後實驗結果是,加載圖片巨慢。而且容易導致卡頓。
所以,我將希望轉向了universal-image-loader和volley。
聽說volley還封裝了異步http。而且是google公司的,所以,我選擇了volley
一篇值得贊賞的文章是:http://blog.csdn.net/sun1021976312/article/details/24672707
說真的。本文的理論部分,也是轉自它。我們在後面進行封裝,然後使用然後展示效果。
Volley是將AsyncHttpClient和Universal-Image-Loader的優點集成於一身的一個框架。我們都知道,Universal-Image-Loader具備非常強大的加載網絡圖片的功能,而使用Volley,我們也可以實現基本類似的效果,並且在性能上也豪不遜色於Universal-Image-Loader,下面我們就來具體學習一下吧。
1. ImageRequest的用法
前面我們已經學習過了StringRequest和JsonRequest的用法,並且總結出了它們的用法都是非常類似的,基本就是進行以下三步操作即可:
1. 創建一個RequestQueue對象。
2. 創建一個Request對象。
3. 將Request對象添加到RequestQueue裡面。
其中,StringRequest和JsonRequest都是繼承自Request的,所以它們的用法才會如此類似。那麼不用多說,今天我們要學習的ImageRequest,相信你從名字上就已經猜出來了,它也是繼承自Request的,因此它的用法也是基本相同的,首先需要獲取到一個RequestQueue對象,可以調用如下方法獲取到:
[java] view
plaincopy

-
RequestQueue mQueue = Volley.newRequestQueue(context);
接下來自然要去new出一個ImageRequest對象了,代碼如下所示:
[java] view
plaincopy

-
ImageRequest imageRequest = new ImageRequest(
-
"http://developer.android.com/images/home/aw_dac.png",
-
new Response.Listener() {
-
@Override
-
public void onResponse(Bitmap response) {
-
imageView.setImageBitmap(response);
-
}
-
}, 0, 0, Config.RGB_565, new Response.ErrorListener() {
-
@Override
-
public void onErrorResponse(VolleyError error) {
-
imageView.setImageResource(R.drawable.default_image);
-
}
-
});
可以看到,ImageRequest的構造函數接收六個參數,第一個參數就是圖片的URL地址,這個沒什麼需要解釋的。第二個參數是圖片請求成功的回調,這裡我們把返回的Bitmap參數設置到ImageView中。第三第四個參數分別用於指定允許圖片最大的寬度和高度,如果指定的網絡圖片的寬度或高度大於這裡的最大值,則會對圖片進行壓縮,指定成0的話就表示不管圖片有多大,都不會進行壓縮。第五個參數用於指定圖片的顏色屬性,Bitmap.Config下的幾個常量都可以在這裡使用,其中ARGB_8888可以展示最好的顏色屬性,每個圖片像素占據4個字節的大小,而RGB_565則表示每個圖片像素占據2個字節大小。第六個參數是圖片請求失敗的回調,這裡我們當請求失敗時在ImageView中顯示一張默認圖片。
最後將這個ImageRequest對象添加到RequestQueue裡就可以了,如下所示:
[java] view
plaincopy
-
mQueue.add(imageRequest);
現在如果運行一下程序,並嘗試發出這樣一條網絡請求,很快就能看到網絡上的圖片在ImageView中顯示出來了,如下圖所示:

2. ImageLoader的用法
如果你覺得ImageRequest已經非常好用了,那我只能說你太容易滿足了 ^_^。實際上,Volley在請求網絡圖片方面可以做到的還遠遠不止這些,而ImageLoader就是一個很好的例子。ImageLoader也可以用於加載網絡上的圖片,並且它的內部也是使用ImageRequest來實現的,不過ImageLoader明顯要比ImageRequest更加高效,因為它不僅可以幫我們對圖片進行緩存,還可以過濾掉重復的鏈接,避免重復發送請求。
由於ImageLoader已經不是繼承自Request的了,所以它的用法也和我們之前學到的內容有所不同,總結起來大致可以分為以下四步:
1. 創建一個RequestQueue對象。<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+CjIuILS0vajSu7j2SW1hZ2VMb2FkZXK21M/zoaM8L3A+CjxwPgozLiC78cih0ru49kltYWdlTGlzdGVuZXK21M/zoaM8L3A+CjxwPgo0LiC199PDSW1hZ2VMb2FkZXK1xGdldCgpt723qLzT1NjN+MLnyc+1xM28xqyhozwvcD4KPHA+Cs/Cw+bO0sPHvs3AtLC01dXV4rj2sr3W6KOs0afPsNK7z8JJbWFnZUxvYWRlcrXE08O3qLDJoaPK18/ItdrSu7K9tcS0tL2oUmVxdWVzdFF1ZXVlttTP887Sw8fS0b6t0LS5/brctuCx6cHLo6zP4NDF0tG+rbK708PU2dbYuLS96cncwcujrMTHw7S+zbTTtdq2/rK9v6rKvNGnz7CwyaOs0MK9qNK7uPZJbWFnZUxvYWRlcrbUz/OjrLT6wuvI58/Cy/nKvqO6PC9wPgoKCgo8c3Ryb25nPltqYXZhXTwvc3Ryb25nPiB2aWV3CiBwbGFpbmNvcHk8aW1nIHNyYz0="https://www.android5.online/Android/UploadFiles_5356/201702/2017022316263379.png" width="12" height="12" alt="在CODE上查看代碼片">
-
ImageLoader imageLoader = new ImageLoader(mQueue, new ImageCache() {
-
@Override
-
public void putBitmap(String url, Bitmap bitmap) {
-
}
-
-
@Override
-
public Bitmap getBitmap(String url) {
-
return null;
-
}
-
});
可以看到,ImageLoader的構造函數接收兩個參數,第一個參數就是RequestQueue對象,第二個參數是一個ImageCache對象,這裡我們先new出一個空的ImageCache的實現即可。
接下來需要獲取一個ImageListener對象,代碼如下所示:
[java] view
plaincopy
-
ImageListener listener = ImageLoader.getImageListener(imageView,
-
R.drawable.default_image, R.drawable.failed_image);
我們通過調用ImageLoader的getImageListener()方法能夠獲取到一個ImageListener對象,getImageListener()方法接收三個參數,第一個參數指定用於顯示圖片的ImageView控件,第二個參數指定加載圖片的過程中顯示的圖片,第三個參數指定加載圖片失敗的情況下顯示的圖片。
最後,調用ImageLoader的get()方法來加載圖片,代碼如下所示:
[java] view
plaincopy
-
imageLoader.get("http://img.my.csdn.net/uploads/201404/13/1397393290_5765.jpeg", listener);
get()方法接收兩個參數,第一個參數就是圖片的URL地址,第二個參數則是剛剛獲取到的ImageListener對象。當然,如果你想對圖片的大小進行限制,也可以使用get()方法的重載,指定圖片允許的最大寬度和高度,如下所示:
[java] view
plaincopy
-
imageLoader.get("http://img.my.csdn.net/uploads/201404/13/1397393290_5765.jpeg",
-
listener, 200, 200);
現在運行一下程序並開始加載圖片,你將看到ImageView中會先顯示一張默認的圖片,等到網絡上的圖片加載完成後,ImageView則會自動顯示該圖,效果如下圖所示。

雖然現在我們已經掌握了ImageLoader的用法,但是剛才介紹的ImageLoader的優點卻還沒有使用到。為什麼呢?因為這裡創建的ImageCache對象是一個空的實現,完全沒能起到圖片緩存的作用。其實寫一個ImageCache也非常簡單,但是如果想要寫一個性能非常好的ImageCache,最好就要借助Android提供的LruCache功能了,如果你對LruCache還不了解,可以參考我之前的一篇博客Android高效加載大圖、多圖解決方案,有效避免程序OOM。
這裡我們新建一個BitmapCache並實現了ImageCache接口,如下所示:
[java] view
plaincopy
-
public class BitmapCache implements ImageCache {
-
-
private LruCache mCache;
-
-
public BitmapCache() {
-
int maxSize = 10 * 1024 * 1024;
-
mCache = new LruCache(maxSize) {
-
@Override
-
protected int sizeOf(String key, Bitmap bitmap) {
-
return bitmap.getRowBytes() * bitmap.getHeight();
-
}
-
};
-
}
-
-
@Override
-
public Bitmap getBitmap(String url) {
-
return mCache.get(url);
-
}
-
-
@Override
-
public void putBitmap(String url, Bitmap bitmap) {
-
mCache.put(url, bitmap);
-
}
-
-
}
可以看到,這裡我們將緩存圖片的大小設置為10M。接著修改創建ImageLoader實例的代碼,第二個參數傳入BitmapCache的實例,如下所示:
[java] view
plaincopy

-
ImageLoader imageLoader = new ImageLoader(mQueue, new BitmapCache());
這樣我們就把ImageLoader的功能優勢充分利用起來了。
3. NetworkImageView的用法
除了以上兩種方式之外,Volley還提供了第三種方式來加載網絡圖片,即使用NetworkImageView。不同於以上兩種方式,NetworkImageView是一個自定義控制,它是繼承自ImageView的,具備ImageView控件的所有功能,並且在原生的基礎之上加入了加載網絡圖片的功能。NetworkImageView控件的用法要比前兩種方式更加簡單,大致可以分為以下五步:
1. 創建一個RequestQueue對象。
2. 創建一個ImageLoader對象。
3. 在布局文件中添加一個NetworkImageView控件。
4. 在代碼中獲取該控件的實例。
5. 設置要加載的圖片地址。
其中,第一第二步和ImageLoader的用法是完全一樣的,因此這裡我們就從第三步開始學習了。首先修改布局文件中的代碼,在裡面加入NetworkImageView控件,如下所示:
[html] view
plaincopy
-
android:layout_width="fill_parent"
-
android:layout_height="fill_parent"
-
android:orientation="vertical" >
-
-