Volley是由Google開發(fā)的網(wǎng)絡(luò)請求庫,該庫在2013年Google I / O大會上推出的。 由于在Android SDK中缺少在不干擾用戶體驗的情況下進行網(wǎng)絡(luò)請求的庫,因此開發(fā)了Volley庫。 在發(fā)布Volley庫之前,Android程序員如果想在客戶端和后臺之間開發(fā)RESTFul系統(tǒng),只能使用類 就算不考慮使用這兩個類時出現(xiàn)的錯誤,除了簡單的HTTP事務(wù)之外,所有事情都必須從頭開始。 如果想緩存圖像或優(yōu)先處理某個請求,則那么這些都必須從頭開始。 幸運的是,現(xiàn)在有了Volley庫,專門為這些需求而量身打造。 1.為什么使用Volley?避免使用
|
1 | git clone https: //android . /platform/frameworks/volley |
直到幾個星期前,您可以使用ant命令行(android update project -p .
然后 ant jar
)將所有內(nèi)容包裝起來,并使用簡單的compile files('libs/volley.jar')
在Android Studio項目中導(dǎo)入JAR庫 。
最近,Google已將Volley更新為Android Studio構(gòu)建樣式,從而難以創(chuàng)建獨立的JAR包。 您仍然可以這樣做,但只能使用舊版本的庫。 我個人不鼓勵你使用這個選項,盡管看起來最快。
您應(yīng)該以經(jīng)典的方式設(shè)置Volley ,即通過將源代碼導(dǎo)入為module。 在Android Studio中,打開項目后,選擇“ 文件”>“新建模塊”,然后選擇“ 導(dǎo)入現(xiàn)有項目”。 選擇剛剛下載源代碼的目錄并確認。 名為Volley的文件夾將顯示在您的項目結(jié)構(gòu)中。 Android Studio自動更新您的 settings.gradle文件以包含Volley模塊,因此您只需要將compile project(':volley')
添加到依賴關(guān)系即可完成。
有第三種方式。 您可以添加build.gradle文件的依賴關(guān)系部分:
1 | compile 'com.mcxiaoke.volley:library-aar:1.0.15' |
它是官方Google存儲庫的鏡像副本,經(jīng)常同步和更新。 這可能是最簡單和最快速的入門方式了。 但是,請注意,這是一個非官方的 Maven存儲庫,不能保證,也不由Google支持。
在我看來,投入更多的時間導(dǎo)入官方源代碼還是比較好。 這樣,您可以輕松地跳轉(zhuǎn)到原來的定義和實現(xiàn),以便在有疑問的情況下,您可以隨時依靠官方的Volley源代碼,甚至可以根據(jù)需要進行更改。
Volley大多數(shù)情況下只用兩個類工作, RequestQueue
和Request
。 您首先創(chuàng)建一個 RequestQueue
,它管理工作線程并將解析的結(jié)果傳遞回主線程。 然后,給RequestQueue傳遞一個或多個 Request
對象。
Request
構(gòu)造函數(shù)總是把方法類型(GET,POST等)、資源的URL和事件偵聽器作為參數(shù)。 然后,根據(jù)請求的類型,它可能會要求一些更多的變量。
在下面的例子中,我通過調(diào)用一個Volley方法 Volley.newRequestQueue
來創(chuàng)建一個RequestQueue
對象。 這將使用Volley定義的默認值設(shè)置RequestQueue
對象。
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | // Request a string response StringRequest stringRequest = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() { @Override public void onResponse(String response) { // Result handling System.out.println(response.substring( 0 , 100 )); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { // Error handling System.out.println( "Something went wrong!" ); error.printStackTrace(); } }); // Add the request to the queue Volley.newRequestQueue( this ).add(stringRequest); |
正如你所看到的,這是非常簡單的。 您創(chuàng)建請求并將其添加到請求隊列。 你完成了。
請注意,監(jiān)聽器的語法類似于AsyncTask.onPostExecute
,只是它變成了onResponse
。 這不是巧合。 使用Volley的開發(fā)人員有意使庫的API與AsyncTask
方法類似 。 這使得從使用AsyncTask
切換到Volley更容易。
如果您必須在多個activity中進行多個請求,則應(yīng)避免使用上述方法Volley.newRequestQueue.add
。 最好是實例化一個共享的請求隊列,并在您的項目中使用它:
1 | MySingletonClass.getInstance().getRequestQueue().add(myRequest); |
我們將在本系列的下一個教程中專門開發(fā)這樣的東西。
Volley可以實現(xiàn)三種非常常見的請求類型:
StringRequest
ImageRequest
JsonRequest
這些類中的每一個都繼承了我們之前使用的Result
類。 我們已經(jīng)在前面的例子看過StringRequest
了。 讓我們來看看JsonRequest
工作原理。
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | JsonObjectRequest jsonRequest = new JsonObjectRequest (Request.Method.GET, url, null , new Response.Listener<JSONObject>() { @Override public void onResponse(JSONObject response) { // the response is already constructed as a JSONObject! try { response = response.getJSONObject( "args" ); String site = response.getString( "site" ), network = response.getString( "network" ); System.out.println( "Site: " +site+ "\nNetwork: " +network); } catch (JSONException e) { e.printStackTrace(); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { error.printStackTrace(); } }); Volley.newRequestQueue( this ).add(jsonRequest); |
美麗。 不是嗎? 您可以看到,結(jié)果類型已設(shè)置為JSONObject
。 你也可以請求一個JSONArray
如果你想要,使用JsonArrayRequest
而不是一個JsonObjectRequest
進請求。
如前所述,構(gòu)造函數(shù)的第一個參數(shù)是要使用的HTTP方法。 然后,您可以提供從中獲取JSON的URL。 上面的例子中的第三個變量是 null
。 這很好,因為它表示沒有參數(shù)將隨請求一起發(fā)出。 最后,您有監(jiān)聽器接收JSON響應(yīng)和錯誤響應(yīng)。 如果你想忽略錯誤,你可以傳入null
。
獲取圖像需要做更多的工作。 有三種請求圖像的方法。 ImageRequest
是標準的。 它顯示在共同的ImageView
中請求的圖片,該圖片通過提供的URL進行獲取。 您可能希望Volley執(zhí)行的所有解碼和調(diào)整大小操作都發(fā)生在工作線程上。 第二個選項是 ImageLoader
類,您可以將其視為大量的編排者ImageRequests
,例如加載ListView
圖像。 第三個選項是 NetworkImageView
,這是ImageView
布局項的一種XML替代。
我們來看一個例子。
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 | mImageView = (ImageView) findViewById(R.id.image); ImageRequest imgRequest = new ImageRequest(url, new Response.Listener<Bitmap>() { @Override public void onResponse(Bitmap response) { mImageView.setImageBitmap(response); } }, 0 , 0 , ImageView.ScaleType.FIT_XY, Bitmap.Config.ARGB_8888, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { mImageView.setBackgroundColor(Color.parseColor( "#ff0000" )); error.printStackTrace(); } }); Volley.newRequestQueue( this ).add(imgRequest); |
第一個參數(shù)是圖片的URL,第二個參數(shù)是監(jiān)聽結(jié)果的監(jiān)聽器。 第三和第四個參數(shù)是整數(shù)maxWidth
和 maxHeight
。 您可以將它們設(shè)置0
來忽略這些參數(shù)。 之后,ImageRequest
請求ScaleType
用于計算所需的圖像大小和格式來解碼位圖。 我建議解碼格式總是使用Bitmap.Config.ARGB_8888
。 最后,我們傳遞監(jiān)聽錯誤的監(jiān)聽器。
請注意,Volley會自動將此請求的優(yōu)先級設(shè)置為LOW
。
1 2 3 4 5 6 | // Snippet taken from ImageRequest.java, // in the Volley source code @Override public Priority getPriority() { return Priority.LOW; } |
從GET請求切換到POST請求很簡單。 您需要更改Request.Method
請求的構(gòu)造函數(shù)并重寫getParams
方法,返回包含請求參數(shù)的Map<String, String> 。
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | StringRequest postRequest = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() { @Override public void onResponse(String response) { try { JSONObject jsonResponse = new JSONObject(response).getJSONObject( "form" ); String site = jsonResponse.getString( "site" ), network = jsonResponse.getString( "network" ); System.out.println( "Site: " +site+ "\nNetwork: " +network); } catch (JSONException e) { e.printStackTrace(); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { error.printStackTrace(); } } ) { @Override protected Map<String, String> getParams() { Map<String, String> params = new HashMap<>(); // the POST parameters: params.put( "site" , "code" ); params.put( "network" , "tutsplus" ); return params; } }; Volley.newRequestQueue( this ).add(postRequest); |
如果要取消所有請求,請將以下代碼段添加到 onStop
方法中:
01 02 03 04 05 06 07 08 09 10 11 | @Override protected void onStop() { super .onStop(); mRequestQueue.cancelAll( new RequestQueue.RequestFilter() { @Override public boolean apply(Request<?> request) { // do I have to cancel this? return true ; // -> always yes } }); } |
這樣,您就不用擔心用戶在onResponse
被調(diào)用時activity已經(jīng)被銷毀了的可能性。 因為在這種情況下會拋出NullPointerException
異常。
然而,POST和PUT請求應(yīng)該繼續(xù),即使在用戶更改activity之后。 我們可以通過使用標簽來實現(xiàn)。 構(gòu)建GET請求時,向其添加一個標簽。
1 2 3 | // after declaring your request request.setTag( "GET" ); mRequestQueue.add(request); |
要取消所有待處理的GET請求,我們只需添加以下代碼行:
1 | mRequestQueue.cancelAll( "GET" ); |
這樣,您只能取消GET請求,使其他請求保持不變。 請注意,您現(xiàn)在必須手動處理activity過早銷毀的情況。
Volley不提供設(shè)置請求的Cookie的方法,也不提供設(shè)置優(yōu)先級。 這可能在將來研究,因為它是一個嚴重的遺漏。 但是,暫時還要繼承Request
類。
對于管理cookies,您可以使用請求的標題來重寫getHeaders
方法:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | public class CustomRequest extends JsonObjectRequest { // Since we're extending a Request class // we just use its constructor public CustomRequest( int method, String url, JSONObject jsonRequest, Response.Listener<JSONObject> listener, Response.ErrorListener errorListener) { super (method, url, jsonRequest, listener, errorListener); } private Map<String, String> headers = new HashMap<>(); /** * Custom class! */ public void setCookies(List<String> cookies) { StringBuilder sb = new StringBuilder(); for (String cookie : cookies) { sb.append(cookie).append( "; " ); } headers.put( "Cookie" , sb.toString()); } @Override public Map<String, String> getHeaders() throws AuthFailureError { return headers; } } |
實現(xiàn)后,您可以使用setCookies
直接提供請求的Cookie列表。
01 02 03 04 05 06 07 08 09 10 11 12 | // Firstly, you create the list of the cookies, // conformed to the HTTP conventions // i.e. key=value List<String> cookies = new ArrayList<>(); cookies.add( "site=code" ); cookies.add( "network=tutsplus" ); // then you invoke your custom method customRequest.setCookies(cookies); // and finally add the request to the queue Volley.newRequestQueue( this ).add(customRequest); |
對于優(yōu)先級,您還需要繼承Request
類,重寫getPriority
方法。 實現(xiàn)如下:
01 02 03 04 05 06 07 08 09 10 11 12 | Priority mPriority; public void setPriority(Priority priority) { mPriority = priority; } @Override public Priority getPriority() { // If you didn't use the setPriority method, // the priority is automatically set to NORMAL return mPriority != null ? mPriority : Priority.NORMAL; } |
然后,在主線程上,調(diào)用這一行代碼來設(shè)置請求的優(yōu)先級:
1 | customRequest.setPriority(Priority.HIGH); |
您可以選擇以下四個可能的優(yōu)先級狀態(tài)之一:
1 2 3 4 | Priority.LOW // images, thumbnails, ... Priority.NORMAL // residual Priority.HIGH // descriptions, lists, ... Priority.IMMEDIATE // login, logout, ... |
在本文中,我們研究了Volley網(wǎng)絡(luò)庫的工作原理。 我們首先看到了為什么使用Volley,何時使用Volley而不是已經(jīng)包含在Android SDK中的另一個解決方案。 然后,我們深入了解該庫的細節(jié),查看其工作流程及其支持的請求類型。 最后,我們通過創(chuàng)建簡單的請求并實現(xiàn)自定義的請求來處理cookie和優(yōu)先級,從而達到我們的目的。
在本系列關(guān)于Volley的下一部分中,我們將創(chuàng)建一個利用Volley的簡單應(yīng)用程序。 我將展示如何制作火星天氣應(yīng)用程序,使用好奇流動站在火星上收集的天氣數(shù)據(jù)。
|