Volley框架的使用

Volley框架

Volley是Google官方出的一套小而巧的異步請求庫,該框架封裝的擴展性很強,支持HttpClient、HttpUrlConnection,甚至支持OkHttp,而且Volley里面也封裝了ImageLoader,所以如果你愿意你甚至不需要使用圖片加載框架,不過這塊功能沒有一些專門的圖片加載框架強大,對于簡單的需求可以使用,對于稍復雜點的需求還是需要用到專門的圖片加載框架。

Volley也有缺陷,比如不支持post大數據,所以不適合上傳文件。不過Volley設計的初衷本身也就是為頻繁的、數據量小的網絡請求而生!

AndroidStudio中引入Volley

·引入volley.jar文件

·添加volley到gradle依賴(非官方)

·通過git下載volley,添加為項目module

Volley基本使用

這里以JsonRequest為例首先我們需要創建一個RequestQueue requestQueue,然后構建一個自己所需要的XXRequest

req,之后通過requestQueue.add(req);將請求添加至請求隊列;

1.構建一個RequestQueue

RequestQueue

requestQueue=Volley.newRequestQueue(this);//這里的this指的是Context

2.創建一個Request(以JsonObjectRequest為例)

private final String

url="http:/xxxxx"http://所需url

JsonObjectRequest req=newJsonObjectRequest(url,null,new Response.Listener(){

@Override

public void onResponse(JsonObjectresponse){

//添加自己的響應邏輯,

}

},

new ResponseError.Listener(){

@Override

public void onResponseError(VollerErrorerror){

//錯誤處理

L.d("ErrorMessage:","Error is"+error);

}

})

3.將req添加到requestQueue

requestQueue.add(req);在構建JsonObjectRequest對象時,需要四個參數,其中第二個參數代表http方法,第三個和第四個分別是響應監聽和響應錯誤監聽,分別需要覆寫onResponse()和onResponseError()方法;RequestQueue將會執行請求,并將響應回調onResponse()方法,所以需要在onResponse()方法中實現自己的業務邏輯

4.?ImageRequest的用法

不同的地方就是,添加Request:

ImageRequest?imageRequest?=newImageRequest(

"url",

newResponse.Listener()?{

@Override

publicvoidonResponse(Bitmap?response)?{

imageView.setImageBitmap(response);

}

},?0,?0,?Config.RGB_565,newResponse.ErrorListener()?{

@Override

publicvoidonErrorResponse(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)。

5.ImageLoader的用法

ImageLoader也可以用于加載網絡上的圖片,并且它的內部也是使用ImageRequest來實現的,不過ImageLoader明顯要比ImageRequest更加高效,因為它不僅可以幫我們對圖片進行緩存,還可以過濾掉重復的鏈接,避免重復發送請求。

由于ImageLoader已經不是繼承自Request的了,所以它的用法也和我們之前學到的內容有所不同,總結起來大致可以分為以下四步:

1.創建一個RequestQueue對象。

2.創建一個ImageLoader對象。

3.獲取一個ImageListener對象。

4.調用ImageLoader的get()方法加載網絡上的圖片。

首先第一步的創建RequestQueue對象這里就不再重復介紹了,那么就從第二步開始,新建一個ImageLoader對象,代碼如下所示:

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控件,第二個參數指定加載圖片的過程中顯示的圖片,第三個參數指定加載圖片失敗的情況下顯示的圖片。

最后,調用ImageLoader的get()方法來加載圖片,代碼如下所示:

imageLoader.get("url",?listener);

get()方法接收兩個參數,第一個參數就是圖片的URL地址,第二個參數則是剛剛獲取到的ImageListener對象。當然,如果你想對圖片的大小進行限制,也可以使用get()方法的重載,指定圖片允許的最大寬度和高度,如下所示:

imageLoader.get("url",?listener,?200,?200);

雖然現在我們已經掌握了ImageLoader的用法,但是剛才介紹的ImageLoader的優點卻還沒有使用到。為什么呢?因為這里創建的ImageCache對象是一個空的實現,完全沒能起到圖片緩存的作用。其實寫一個ImageCache也非常簡單,但是如果想要寫一個性能非常好的ImageCache,最好就要借助Android提供的LruCache功能了,這里就不做介紹了,有興趣的可以看一下LruCache。

6.NetworkImageView的用法

除了以上兩種方式之外,Volley還提供了第三種方式來加載網絡圖片,即使用NetworkImageView。不同于以上兩種方式,NetworkImageView是一個自定義控制,它是繼承自ImageView的,具備ImageView控件的所有功能,并且在原生的基礎之上加入了加載網絡圖片的功能。NetworkImageView控件的用法要比前兩種方式更加簡單,大致可以分為以下五步:

1.創建一個RequestQueue對象。

2.創建一個ImageLoader對象。

3.在布局文件中添加一個NetworkImageView控件。

4.在代碼中獲取該控件的實例。

5.設置要加載的圖片地址。

其中,第一第二步和ImageLoader的用法是完全一樣的,因此這里我們就從第三步開始學習了。首先修改布局文件中的代碼,在里面加入NetworkImageView控件,如下所示:

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:orientation="vertical"?>

android:id="@+id/button"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="Send?Request"?/>

android:id="@+id/network_image_view"

android:layout_width="200dp"

android:layout_height="200dp"

android:layout_gravity="center_horizontal"

/>

接著在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("url",??imageLoader);

其中,setImageUrl()方法接收兩個參數,第一個參數用于指定圖片的URL地址,第二個參數則是前面創建好的ImageLoader對象。

定制自己的Request

1.自定義XMLRequest

自定義一個XMLRequest,用于請求一條XML格式的數據。那么該從哪里開始入手呢?額,好像是有些無從下手。遇到這種情況,我們應該去參考一下Volley的源碼,看一看StringRequest是怎么實現的,然后就可以模仿著寫出XMLRequest了。首先看下StringRequest的源碼,如下所示:

/**

*?A?canned?request?for?retrieving?the?response?body?at?a?given?URL?as?a?String.

*/

public?class?StringRequest?extends?Request?{

private?final?Listener?mListener;

/**

*?Creates?a?new?request?with?the?given?method.

*

*?@param?method?the?request?{@link?Method}?to?use

*?@param?url?URL?to?fetch?the?string?at

*?@param?listener?Listener?to?receive?the?String?response

*?@param?errorListener?Error?listener,?or?null?to?ignore?errors

*/

public?StringRequest(int?method,?String?url,?Listener?listener,

ErrorListener?errorListener)?{

super(method,?url,?errorListener);

mListener?=?listener;

}

/**

*?Creates?a?new?GET?request.

*

*?@param?url?URL?to?fetch?the?string?at

*?@param?listener?Listener?to?receive?the?String?response

*?@param?errorListener?Error?listener,?or?null?to?ignore?errors

*/

public?StringRequest(String?url,?Listener?listener,?ErrorListener?errorListener)?{

this(Method.GET,?url,?listener,?errorListener);

}

@Override

protected?void?deliverResponse(String?response)?{

mListener.onResponse(response);

}

@Override

protected?Response?parseNetworkResponse(NetworkResponse?response)?{

String?parsed;

try?{

parsed?=?new?String(response.data,?HttpHeaderParser.parseCharset(response.headers));

}?catch?(UnsupportedEncodingException?e)?{

parsed?=?new?String(response.data);

}

return?Response.success(parsed,?HttpHeaderParser.parseCacheHeaders(response));

}

}

可以看到,首先StringRequest是繼承自Request類的,Request可以指定一個泛型類,這里指定的當然就是String了,接下來StringRequest中提供了兩個有參的構造函數,參數包括請求類型,請求地址,以及響應回調等,需要注意的是,在構造函數中一定要調用super()方法將這幾個參數傳給父類,因為HTTP的請求和響應都是在父類中自動處理的。

另外,由于Request類中的deliverResponse()和parseNetworkResponse()是兩個抽象方法,因此StringRequest中需要對這兩個方法進行實現。deliverResponse()方法中的實現很簡單,僅僅是調用了mListener中的onResponse()方法,并將response內容傳入即可,這樣就可以將服務器響應的數據進行回調了。parseNetworkResponse()方法中則應該對服務器響應的數據進行解析,其中數據是以字節的形式存放在NetworkResponse的data變量中的,這里將數據取出然后組裝成一個String,并傳入Response的success()方法中即可。

了解了StringRequest的實現原理,下面我們就可以動手來嘗試實現一下XMLRequest了,代碼如下所示:

public?class?XMLRequest?extends?Request?{

private?final?Listener?mListener;

public?XMLRequest(int?method,?String?url,?Listener?listener,

ErrorListener?errorListener)?{

super(method,?url,?errorListener);

mListener?=?listener;

}

public?XMLRequest(String?url,?Listener?listener,?ErrorListener?errorListener)?{

this(Method.GET,?url,?listener,?errorListener);

}

@Override

protected?Response?parseNetworkResponse(NetworkResponse?response)?{

try?{

String?xmlString?=?new?String(response.data,

HttpHeaderParser.parseCharset(response.headers));

XmlPullParserFactory?factory?=?XmlPullParserFactory.newInstance();

XmlPullParser?xmlPullParser?=?factory.newPullParser();

xmlPullParser.setInput(new?StringReader(xmlString));

return?Response.success(xmlPullParser,?HttpHeaderParser.parseCacheHeaders(response));

}?catch?(UnsupportedEncodingException?e)?{

return?Response.error(new?ParseError(e));

}?catch?(XmlPullParserException?e)?{

return?Response.error(new?ParseError(e));

}

}

@Override

protected?void?deliverResponse(XmlPullParser?response)?{

mListener.onResponse(response);

}

}

可以看到,基本都是仿照StringRequest寫下來的,XMLRequest也是繼承自Request類的,只不過這里指定的泛型類是XmlPullParser,說明我們準備使用Pull解析(XML解析方式dom、sax、pull)的方式來解析XML。在parseNetworkResponse()方法中,先是將服務器響應的數據解析成一個字符串,然后設置到XmlPullParser對象中,在deliverResponse()方法中則是將XmlPullParser對象進行回調。

2.自定義GsonRequest

JsonRequest的數據解析是利用Android本身自帶的JSONObject和JSONArray來實現的,配合使用JSONObject和JSONArray就可以解析出任意格式的JSON數據。不過也許你會覺得使用JSONObject還是太麻煩了,還有很多方法可以讓JSON數據解析變得更加簡單,比如說GSON。遺憾的是,Volley中默認并不支持使用自家的GSON來解析數據,不過沒有關系,通過上面的學習,相信你已經知道了自定義一個Request是多么的簡單,那么下面我們就來舉一反三一下,自定義一個GsonRequest。

首先我們需要把gson的jar包添加到項目當中,jar包的下載地址是:https://code.google.com/p/google-gson/downloads/list

接著定義一個GsonRequest繼承自Request,代碼如下所示:

public?class?GsonRequest?extends?Request?{

private?final?Listener?mListener;

private?Gson?mGson;

private?Class?mClass;

public?GsonRequest(int?method,?String?url,?Class?clazz,?Listener?listener,

ErrorListener?errorListener)?{

super(method,?url,?errorListener);

mGson?=?new?Gson();

mClass?=?clazz;

mListener?=?listener;

}

public?GsonRequest(String?url,?Class?clazz,?Listener?listener,

ErrorListener?errorListener)?{

this(Method.GET,?url,?clazz,?listener,?errorListener);

}

@Override

protected?Response?parseNetworkResponse(NetworkResponse?response)?{

try?{

String?jsonString?=?new?String(response.data,

HttpHeaderParser.parseCharset(response.headers));

return?Response.success(mGson.fromJson(jsonString,?mClass),

HttpHeaderParser.parseCacheHeaders(response));

}?catch?(UnsupportedEncodingException?e)?{

return?Response.error(new?ParseError(e));

}

}

@Override

protected?void?deliverResponse(T?response)?{

mListener.onResponse(response);

}

}

可以看到,GsonRequest是繼承自Request類的,并且同樣提供了兩個構造函數。在parseNetworkResponse()方法中,先是將服務器響應的數據解析出來,然后通過調用Gson的fromJson方法將數據組裝成對象。在deliverResponse方法中仍然是將最終的數據進行回調

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,739評論 6 534
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,634評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,653評論 0 377
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,063評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,835評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,235評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,315評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,459評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,000評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,819評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,004評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,560評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,257評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,676評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,937評論 1 288
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,717評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,003評論 2 374

推薦閱讀更多精彩內容