Android中關於Volley的使用(一)加載圖片

在Android中,如果我們要展示的圖片是存儲在網絡上的時候,我們就必須通過HttpClient或者HttpUrlConnection這兩個類來進行關於網絡方面的操作,比如下面中利用GridView來展示幾個圖片:

關於GridView如何來展示圖片就不多講瞭,這個其實是跟ListView利用BaseAdapter來展示的原理是一樣的,大傢有興趣可以下面的文章看一下:

Android中關於Adapter的使用(下)BaseAdapter
vcD4KPHA+1NrV4sDvo6zO0sPHz8i/tNK7z8LU9cO0wPvTw0h0dHBVcmxDb25uZWN0aW9uwLS78cihzfjC58nPtcTNvMastcShozwvcD4KPHA+MaOpytfPyMrHzbzGrNS0o7o8L3A+CjxwPjxwcmUgY2xhc3M9″brush:java;”> private static final String[] URLS = {
“https://img.my.csdn.net/uploads/201403/03/1393854094_4652.jpg”,
“https://img.my.csdn.net/uploads/201403/03/1393854084_6138.jpg”,
“https://img.my.csdn.net/uploads/201403/03/1393854084_1323.jpg”,
“https://img.my.csdn.net/uploads/201403/03/1393854084_8439.jpg”,
“https://img.my.csdn.net/uploads/201403/03/1393854083_6511.jpg”,
“https://img.my.csdn.net/uploads/201403/03/1393854083_2323.jpg”
};

private static final String[] DESCS = {
“photo1″,”photo2″,”photo3″,”photo4″,”photo5″,”photo6”
};
2)在BaseAdapter的getView方法中,我們要去獲取網絡上的圖片,並將其轉化為Bitmap,代碼如下:

	viewHolder.ivImage.setImageBitmap(readBitmapFromUrl(URLS[position]));
	...
	
	public Bitmap readBitmapFromUrl(String imgUrl){
		BitmapFactory.Options op = new BitmapFactory.Options();
		op.inPreferredConfig = Bitmap.Config.ARGB_8888;
		op.inDither = false;
		op.inScaled = false;
		Bitmap bitmap = null;
		try {
			URL url = new URL(imgUrl);			
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			conn.setConnectTimeout(3 * 1000);
			
			if(conn.getResponseCode() != 200){ 
				throw new RuntimeException("Request Failed");
			}
			InputStream is = conn.getInputStream();
			
			bitmap = BitmapFactory.decodeStream(is,null,op);
			
			bitmap = Helper.zoomBitmap(bitmap, 150, 150);
			
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}		
		return bitmap;
	}

在這裡,我們首先根據參數imgUrl定義瞭URL對象,並通過openConnection函數返回HttpURLConnection對象,然後利用BitmapFactory的decodeStream方法將Response的stream給解析成對應的Bitmap,而獲取到的圖片可能是比較大的,我們需要將其縮小到適合的大小,以便在屏幕上顯示,於是我們又調用瞭zoomBitamp函數(自定義的函數)來進行一個縮小的操作。

我們會發現,雖然我們能夠利用HttpURLConnection這樣去實現我們想要的功能,但是需要我們自己去做的事情還是太多瞭,尤其是在上面還沒有考慮圖片非常多的情況,沒有考慮緩存,網絡請求等方面的因素,真的要去考慮,會煩死的。

而且上面的代碼隻是適宜運行在2.3以上,4.0以下的機器,在4.0以上的機器,是不允許我們直接這樣去用HttpURLConnection來進行網絡方面的通訊的,會爆下面的錯誤的,如下:

03-04 23:18:44.773: E/AndroidRuntime(13299): android.os.NetworkOnMainThreadException  
03-04 23:18:44.773: E/AndroidRuntime(13299):    at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1103)  
03-04 23:18:44.773: E/AndroidRuntime(13299):    at java.net.InetAddress.lookupHostByName(InetAddress.java:391)  
03-04 23:18:44.773: E/AndroidRuntime(13299):    at java.net.InetAddress.getAllByNameImpl(InetAddress.java:242)  
03-04 23:18:44.773: E/AndroidRuntime(13299):    at java.net.InetAddress.getAllByName(InetAddress.java:220)  
03-04 23:18:44.773: E/AndroidRuntime(13299):    at libcore.net.http.HttpConnection.(HttpConnection.java:71)  
03-04 23:18:44.773: E/AndroidRuntime(13299):    at libcore.net.http.HttpConnection.(HttpConnection.java:50)  
03-04 23:18:44.773: E/AndroidRuntime(13299):    at libcore.net.http.HttpConnection$Address.connect(HttpConnection.java:351)  
03-04 23:18:44.773: E/AndroidRuntime(13299):    at libcore.net.http.HttpConnectionPool.get(HttpConnectionPool.java:86)  
03-04 23:18:44.773: E/AndroidRuntime(13299):    at libcore.net.http.HttpConnection.connect(HttpConnection.java:128)  
03-04 23:18:44.773: E/AndroidRuntime(13299):    at libcore.net.http.HttpEngine.openSocketConnection(HttpEngine.java:308)  
03-04 23:18:44.773: E/AndroidRuntime(13299):    at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.java:460)  
03-04 23:18:44.773: E/AndroidRuntime(13299):    at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:432)  

我覺得開發的,就要善於去利用各種各樣的工具來減輕我們的時間成本,而Volley就是Android中一個很好的網絡通信的小工具啦,雖然我們自己包裝一下,也能夠做到同樣的功能,但是有時候,人與人之間的的差別還真是在那裡的,有些人就能夠做得很好,而有些人就真的做不到那麼好,跑題瞭,隻是感嘆一下牛人的世界。

那麼如何利用Volley來實現網絡圖片的加載呢?其實有很多種方式的,今天我們就先講一種最簡單的加載方式,代碼如下:

1)定義一個RequestQueue,如下:

private RequestQueue mQueue;

2)在OnCreate方法中對其進行初始化,this其實就是當前Activity,是一個Context類:

mQueue = Volley.newRequestQueue(this);

3)創建ImageRequest對象,並將其添加到mQueue中,如下:

	public void readBitmapViaVolley(String imgUrl, final ImageView imageView) {
		ImageRequest imgRequest = new ImageRequest(imgUrl,
				new Response.Listener() {
					@Override
					public void onResponse(Bitmap arg0) {
						// TODO Auto-generated method stub
						imageView.setImageBitmap(arg0);
					}
				}, 
				300, 
				200, 
				Config.ARGB_8888, 
				new ErrorListener() {
					@Override
					public void onErrorResponse(VolleyError arg0) {
						
					}
				});
		mQueue.add(imgRequest);
	}

在上面,我們可以看到,在ImageRequest的構造函數中,我們就可以直接將一些關於Bitmap的參數給傳進去瞭,比如長寬等信息,然後在其返回的Response.Listener中獲得返回的結果,就是一個Bitmap瞭,並在onResponse函數中對ImageView進行設置,最後將其添加到mQueue中。

4)當上面的一切都做好之後,就可以瞭,實現的效果跟我們利用HttpURLConnection來實現的效果是一模一樣的,而且更快,代碼也簡潔很多,是不?

Volley的功能不僅僅是這樣簡單地用簡潔的代碼來幫我們包裝函數,也不僅僅隻是操作圖片,在其隱藏在後面的代碼中,還做瞭其它一些工作,比如:

1)緩存的使用,包括內存和SD卡

2)網絡請求隊列的處理跟優化

3)圖片加載的優化

4)對JSON數據的優化等

後面有時間,大傢一起來學習學習吧。

發佈留言