參考:https://blog.csdn.net/guolin_blog/article/details/17482095
背景:Android系統中主要提供了兩種方式來進行HTTP通信,HttpURLConnection和HttpClient,但是用法稍微有些複雜的,如果不進行適當封裝的話,很容易就會寫出不少重複代碼。一些Android網絡通信框架也就應運而生,比如說AsyncHttpClient(它把HTTP所有的通信細節全部封裝在了內部,我們只需要簡單調用幾行代碼就可以完成通信操作了)和Universal-Image-Loader(它使得在界面上顯示網絡圖片的操作變得極度簡單,開發者不用關心如何從網絡上獲取圖片,也不用關心開啓線程、回收圖片資源等細節)
2013年Google I/O大會上推出的Volley,把AsyncHttpClient和Universal-Image-Loader的優點集於了一身。
適用場景:數據量不大,但網絡通信頻繁的數據請求
功能一:
StringRequest實現HTTP發送與響應
1. 創建一個RequestQueue對象。
//獲取到一個RequestQueue對象
RequestQueue mQueue = Volley.newRequestQueue(context);
注意這裏拿到的RequestQueue是一個請求隊列對象,它可以緩存所有的HTTP請求,然後按照一定的算法併發地發出這些請求。RequestQueue內部的設計就是非常合適高併發的,因此我們不必爲每一次HTTP請求都創建一個RequestQueue對象,這是非常浪費資源的,基本上在每一個需要和網絡交互的Activity中創建一個RequestQueue對象就足夠了。
2. 創建一個StringRequest對象。
StringRequest stringRequest = new StringRequest("http://www.baidu.com",
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
Log.d("TAG", response);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e("TAG", error.getMessage(), error);
}
});
這裏new出了一個StringRequest對象,StringRequest的構造函數需要傳入三個參數,第一個參數就是目標服務器的URL地址,第二個參數是服務器響應成功的回調,第三個參數是服務器響應失敗的回調。其中,目標服務器地址我們填寫的是百度的首頁,然後在響應成功的回調裏打印出服務器返回的內容,在響應失敗的回調裏打印出失敗的詳細信息。
3. 將StringRequest對象添加到RequestQueue裏面。
mQueue.add(stringRequest);
但是HTTP的請求類型通常有兩種,GET和POST,以上爲GET請求。
以下爲POST請求:
StringRequest中還提供了另外一種四個參數的構造函數,其中第一個參數就是指定請求類型的,使用如下方式進行指定:
StringRequest stringRequest = new StringRequest(Method.POST, url, listener, errorListener);
要提交給服務器的參數又該怎麼設置呢?很遺憾,StringRequest中並沒有提供設置POST參數的方法,但是當發出POST請求的時候,Volley會嘗試調用StringRequest的父類——Request中的getParams()方法來獲取POST參數,那麼解決方法自然也就有了,我們只需要在StringRequest的匿名類中重寫getParams()方法,在這裏設置POST參數就可以了,代碼如下所示:
StringRequest stringRequest = new StringRequest(Method.POST, url, listener, errorListener) {
@Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> map = new HashMap<String, String>();
map.put("params1", "value1");
map.put("params2", "value2");
return map;
}
};
附:JsonRequest的用法
至於它們的用法也基本上沒有什麼特殊之處,先new出一個JsonObjectRequest對象:
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest("http://m.weather.com.cn/data/101010100.html", null,
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
Log.d("TAG", response.toString());
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e("TAG", error.getMessage(), error);
}
});
這裏我們填寫的URL地址是http://m.weather.com.cn/data/101010100.html,這是中國天氣網提供的一個查詢天氣信息的接口,響應的數據就是以JSON格式返回的,然後我們在onResponse()方法中將返回的數據打印出來。
最後再將這個JsonObjectRequest對象添加到RequestQueue裏就可以了:
mQueue.add(jsonObjectRequest);
onResponse()方法中攜帶的參數也正是一個JSONObject對象,之後只需要從JSONObject對象取出我們想要得到的那部分數據就可以了。
功能二:
加載網絡圖片
參考:https://blog.csdn.net/guolin_blog/article/details/17482165
Universal-Image-Loader具備非常強大的加載網絡圖片的功能,而使用Volley,我們也可以實現基本類似的效果,並且在性能上也豪不遜色於Universal-Image-Loader。
1、ImageRequest:
//首先需要獲取到一個RequestQueue對象
RequestQueue mQueue = Volley.newRequestQueue(context);
//new出一個ImageRequest對象
ImageRequest imageRequest = new ImageRequest(
"http://developer.android.com/images/home/aw_dac.png",
new Response.Listener<Bitmap>() {
@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裏:
mQueue.add(imageRequest);
2、ImageLoader:
ImageLoader也可以用於加載網絡上的圖片,並且它的內部也是使用ImageRequest來實現的,不過ImageLoader明顯要比ImageRequest更加高效,因爲它不僅可以幫我們對圖片進行緩存,還可以過濾掉重複的鏈接,避免重複發送請求。
由於ImageLoader已經不是繼承自Request的了,所以它的用法也和我們之前學到的內容有所不同,總結起來大致可以分爲以下四步:
1. 創建一個RequestQueue對象。
2. 創建一個ImageLoader對象。
3. 獲取一個ImageListener對象。
4. 調用ImageLoader的get()方法加載網絡上的圖片。
RequestQueue mQueue = Volley.newRequestQueue(context);
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對象,代碼如下所示:
ImageListener listener = ImageLoader.getImageListener(imageView,
R.drawable.default_image, R.drawable.failed_image);
我們通過調用ImageLoader的getImageListener()方法能夠獲取到一個ImageListener對象,getImageListener()方法接收三個參數,第一個參數指定用於顯示圖片的ImageView控件,第二個參數指定加載圖片的過程中顯示的圖片,第三個參數指定加載圖片失敗的情況下顯示的圖片。
3、NetworkImageView:
不同於以上兩種方式,NetworkImageView是一個自定義控制,它是繼承自ImageView的,具備ImageView控件的所有功能,並且在原生的基礎之上加入了加載網絡圖片的功能。NetworkImageView控件的用法要比前兩種方式更加簡單,大致可以分爲以下五步:
1. 創建一個RequestQueue對象。
2. 創建一個ImageLoader對象。
3. 在佈局文件中添加一個NetworkImageView控件。
4. 在代碼中獲取該控件的實例。
5. 設置要加載的圖片地址。
第一第二步和ImageLoader的用法是完全一樣的,因此這裏我們就從第三步開始學習了。首先修改佈局文件中的代碼,在裏面加入NetworkImageView控件,如下所示:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Send Request" />
<com.android.volley.toolbox.NetworkImageView
android:id="@+id/network_image_view"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_gravity="center_horizontal"
/>
</LinearLayout>
接着在Activity獲取到這個控件的實例,這就非常簡單了,代碼如下所示:
networkImageView = (NetworkImageView) findViewById(R.id.network_image_view);
得到了NetworkImageView控件的實例之後,我們可以調用它的setDefaultImageResId()方法、setErrorImageResId()方法和setImageUrl()方法來分別設置加載中顯示的圖片,加載失敗時顯示的圖片,以及目標圖片的URL地址,如下所示:
networkImageView.setDefaultImageResId(R.drawable.default_image);
networkImageView.setErrorImageResId(R.drawable.failed_image);
networkImageView.setImageUrl("https://img-my.csdn.net/uploads/201404/13/1397393290_5765.jpeg",
imageLoader);
其中,setImageUrl()方法接收兩個參數,第一個參數用於指定圖片的URL地址,第二個參數則是前面創建好的ImageLoader對象。
功能三:
自定義XMLRequest
參考:https://blog.csdn.net/guolin_blog/article/details/17612763
實現機制(原理):
參考:https://blog.csdn.net/guolin_blog/article/details/17656437
我們在主線程中調用RequestQueue的add()方法來添加一條網絡請求,這條請求會先被加入到緩存隊列當中,如果發現可以找到相應的緩存結果就直接讀取緩存並解析,然後回調給主線程。如果在緩存中沒有找到結果,則將這條請求加入到網絡請求隊列中,然後處理髮送HTTP請求,解析響應結果,寫入緩存,並回調主線程。