Volley的基本使用

来源:http://www.cnblogs.com/shouce/archive/2016/03/09/5256646.html
-Advertisement-
Play Games

本人初學,如有紕繆,望指正~ Volley是Google在2003年的I/O大會上推出的通信框架,結合了AsyncHttpClient和Universal-Image-Loader的優點——簡化了http的使用 + 非同步載入圖片的神奇能力。Android中的Http實現主要有HttpUrlConne


本人初學,如有紕繆,望指正~     Volley是Google在2003年的I/O大會上推出的通信框架,結合了AsyncHttpClient和Universal-Image-Loader的優點——簡化了http的使用 + 非同步載入圖片的神奇能力。Android中的Http實現主要有HttpUrlConnection和HttpClient兩種,關於二者的選擇Google在Blog中表示推薦在薑餅小人(API level = 9)及以上的版本中使用Java的HttpUrlConnection而在之前的版本使用Apache的HttpClient,這在Volley這個框架中也有明確的體現。   獲取Volley
git clone https://android.googlesource.com/platform/frameworks/volley
把它編譯成jar文件就可以加入libs了   一、簡單的請求(以StringRequest為例)   Http的通信最主要的部分應該就是發出請求和接收響應了,所以Volley的比較核心的一個類就是RequestQueue,一個請求隊列。它負責管理工作線程,讀寫緩存,和解析、分發響應(具體操作還是由具體的類實現),即將發出的Http請求都會首先聚集在這裡等待工作線程來實現請求。RequestQueue可以被看成一艘載滿Http請求的航空母艦,而工作線程就是彈射器嘍。   所以按照航母起飛飛機的步驟,我們可以猜到利用Volley進行Http通信的簡單步驟:     1.獲取RequestQueue(得到一艘航母,可以是自己造的,也可以是委托別人造的,下麵會提到)     2.實例化一個Request(得到一架飛機,你也知道飛機又很多類型啦)     3.將Request加入RequestQueue,等待工作線程將其發送出去(把飛機從機庫升上起飛甲板,等待彈射器把它扔出去)   起飛偵察機-發出GET請求   按照上面的步驟,第一步就是建立一個請求隊列,最簡單的方法就是用Volley.newRequestQueue(),這是一個特別方便的靜態方法,替我們預設實現了所有需要的東西(網路、緩存等,這些在Volley中都有預設實現),它會返回一個已經開始運行的RequestQueue(相當於別人幫忙造了艘航母)。之後我們需要的只是設置好請求的響應監聽介面,把請求加入到這個隊列中就可以等著響應數據來敲門了。下麵是Google文檔中的示例代碼: 複製代碼
 1   //初始化一個請求隊列
 2   RequestQueue queue = Volley.newRequestQueue(this);
 3   String url ="http://www.google.com";
 4   
 5   //根據給定的URL新建一個請求
 6   StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
 7               new Response.Listener() {
 8       @Override
 9       public void onResponse(String response) {
10          //在這裡操作UI組件是安全的,因為響應返回時這個函數會被post到UI線程來執行
11          // 在這裡盡情蹂躪響應的String。
12      }
13  }, new Response.ErrorListener() {
14      @Override
15      public void onErrorResponse(VolleyError error) {
16          // 出錯了怎麼辦?涼拌!並且在這裡拌。
17      }
18 });
19 // 把這個請求加入請求隊列
20 queue.add(stringRequest);
複製代碼 StringRequest是Request的具體實現之一,代表解析後的響應數據是一個字元串,相似的還有JsonRequest(包括JsonObjectRequest和JsonArrayRequest兩個可以使用的子類)、ImageRequest來滿足基本的使用,用法大同小異。主要是構造參數不一樣,分別如下:   1.public StringRequest(int method, String url, Listener<String> listener,ErrorListener errorListener);      參數說明:從左到右分別是請求方法(都封裝在Request中的Method介面內),請求URL,響應監聽介面實例,錯誤監聽介面實例。
  2.public JsonObjectRequest(int method, String url, JSONObject jsonRequest,Listener<JSONObject> listener, ErrorListener errorListener);      public JsonObjectRequest(String url, JSONObject jsonRequest, Listener<JSONObject> listener,ErrorListener errorListener);      參數說明:如果是GET請求的話,jsonRequest傳入null就可以了,否則在未指明請求方法的情況下(也就是第二個構造函數)會預設為POST請求。其他同上。   3.public JsonArrayRequest(String url, Listener<JSONArray> listener, ErrorListener errorListener);      參數說明:同上。   4.public ImageRequest(String url, Response.Listener<Bitmap> listener, int maxWidth, int maxHeight,Config decodeConfig, Response.ErrorListener errorListener);      參數說明:decodeConfig是圖片的顏色屬性,下麵的幾個值都可以使用。  
Bitmap.Config中的顏色屬性(枚舉類型)
ALPHA_8  
ARGB_4444 由於質量低,已經被棄用,推薦用ARGB_8888
ARGB_8888 每個像素用4byte存儲
RGB_565 每個像素用2byte存儲,紅色占5位,綠色占6位,藍色占5位
  起飛戰鬥機-發出POST請求   基本方式和上面一樣,但是怎麼裝導彈,啊不,是怎麼提交的數據呢? Volley會在Request的請求方法是POST(還有PUT和PATCH)的情況下調用Request類(就是XXXRequest的父類)的getParam()函數來獲取參數,提前劇透,如果使用的是HttpUrlConnection的話,調用getParam()是在HurlStatck中的addBodyIfExists()函數實現的,感興趣的話可以去看一下哈。所以,POST請求像下麵這樣就可以了。 複製代碼
 1 //初始化一個請求隊列
 2 RequestQueue queue = Volley.newRequestQueue(this);
 3 String url ="http://www.google.com";
 4 
 5 //根據給定的URL新建一個請求
 6 StringRequest stringRequest = new StringRequest(Request.Method.POST, url,
 7    new Response.Listener() {
 8     @Override
 9     public void onResponse(String response) {
10         // 在這裡處理請求得到的String類型的響應
11    }
12 }, new Response.ErrorListener() {
13     @Override
14     public void onErrorResponse(VolleyError error) {
15         // 在這裡進行出錯之後的處理
16    }
17 }) {
18 @Override
19 protected Map<String, String> getParams() throws AuthFailureError {
20 
21 Map<String, String> map = new HashMap<String, String>(); 
22         map.put("params1", "value1"); 
23         map.put("params2", "value2"); 
24         return map
25  };
26 // 把這個請求加入請求隊列
27 queue.add(stringRequest);
複製代碼   後悔藥-取消請求   Request中有一個cancel()方法,調用這個就可以取消當前請求了,但是取消到哪一個層次就不一定了,但是Volley可以保證響應處理函數(就是onResponse()和onErroeResponse())不會被調用。還有一個一起取消多個請求,就是在發出請求前調用Request的setTag()方法為每個請求加一個標簽,這個方法的參數是Object,所以我們可以使用任何類型作為標簽。這樣就可以調用ReqiestQueue的cancelAll()函數取消一群標簽了。比較常用的方法就是,將發出這個請求的Activity或者Fragment作為標簽,併在onStop()中調用cancelAll()。   二、使用ImageLoader載入圖片   ImageLoader是一個可以實現圖片非同步載入的類,但已經不是繼承與Request了。ImageLoader雖然是頭神獸,但必須在主線程召喚它,否則會拋出錯誤IllegalStateException,可能是因為ImageLoader在圖片返回時要直接操作ImageView,在主線程里操作UI組件才是安全的,so~   用ImageLoader載入圖片分三步     1.創建ImageLoader     2.獲取一個ImageListener對象     3.調用ImageLoader的get()方法獲取圖片   ImageLoader的構造函數長成這樣:public ImageLoader(RequestQueue queue, ImageCache imageCache); 所以實例化一個ImageLoader需要一個RequestQueue(之前建立的就行),還有一個ImageCache,這是一個ImageLoader內部定義的介面,用來實現L1緩存——記憶體緩存(Volley在RequestQueue中已經實現了L2緩存——文件緩存)。ImageLoader中並沒有對傳入的ImageCache在使用前判空的代碼,傳null進去會出錯的。如果實在不想弄記憶體緩存,實現一個什麼都不做的ImageCache就好了。下麵是代碼: 複製代碼
 1 ImageLoader imageLoader = new ImageLoader(mRequestQueue, new ImageCache() {  
 2     @Override  
 3     public void putBitmap(String url, Bitmap bitmap) {  
 4     }  
 5   
 6     @Override  
 7     public Bitmap getBitmap(String url) {  
 8         return null;  
 9     }  
10 });
11 
12 //default_image是正在載入圖片時占位用的
13 //error_image是載入不成功時顯示的圖片
14 ImageListener listener = ImageLoader.getImageListener(imageView, R.drawable.default_image, R.drawable.error_image); 
15imageLoader.get("your image url", listener); 
複製代碼   除了ImageLoader之外Volley中還有一個Image載入的神器——NetworkImageView,使用步驟如下:     1.在佈局文件中加入控制項,併在Java代碼中獲取實例     2.設置default_image,error_image,圖片URL,一個ImageLoader對象   代碼如下:
1 networkImageView = (NetworkImageView) findViewById(R.id.network_image_view); 
2 networkImageView.setDefaultImageResId(R.drawable.default_image);  
3 networkImageView.setErrorImageResId(R.drawable.error_image);
4 networkImageView.setImageUrl("your image url", imageLoader);  

 

三、Google推薦的用法   上面就是Volley的基本用法了,但是如果一個App需要頻繁的網路通信的話,建立多個RequestQueue是件很奇怪的事兒(誰會因為臨時有飛機要在海上起飛就去新建一艘航母呢,這得多有錢啊),所以Google推薦我們只實例化一個RequestQueue來應付頻繁的Http通信,當然,要保證隊列的壽命和App一樣長。如何實現呢?Google又說了,不推薦在App的Application.onCretae()方法中實例化一個RequestQueue(不過確實是個簡單的方法哈),最好是建立一個單例模式的類,並把所有我們需要用到的Volley的瓶瓶罐罐都放進去,這樣顯得更模塊化。下麵就是示例代碼。這段代碼中最重要的就是RequestQueue要用Application的Context實例化,要不然就會隨著Activity的生命周期不停重建。其實,像AsyncHttpClient中的純靜態使用方法也不錯(詳情見:http://loopj.com/android-async-http/) PS:下麵還實現了一個簡單的ImageCache 複製代碼
 1 private static MySingleton mInstance;
 2     private RequestQueue mRequestQueue;
 3     private ImageLoader mImageLoader;
 4     private static Context mCtx;
 5 
 6     private MySingleton(Context context) {
 7         mCtx = context;
 8         mRequestQueue = getRequestQueue();
 9 
10         mImageLoader = new ImageLoader(mRequestQueue,
11                 new ImageLoader.ImageCache() {
12             private final LruCache<String, Bitmap>
13                     cache = new LruCache<String, Bitmap>(20);
14 
15             @Override
16             public Bitmap getBitmap(String url) {
17                 return cache.get(url);
18             }
19 
20             @Override
21             public void putBitmap(String url, Bitmap bitmap) {
22                 cache.put(url, bitmap);
23             }
24         });
25     }
26 
27     public static synchronized MySingleton getInstance(Context context) {
28         if (mInstance == null) {
29             mInstance = new MySingleton(context);
30         }
31         return mInstance;
32     }
33 
34     public RequestQueue getRequestQueue() {
35         if (mRequestQueue == null) {
36             // getApplicationContext()是關鍵, 它會避免
37             // Activity或者BroadcastReceiver帶來的缺點.
38             mRequestQueue = Volley.newRequestQueue(mCtx.getApplicationContext());
39         }
40         return mRequestQueue;
41     }
42 
43     public <T> void addToRequestQueue(Request<T> req) {
44         getRequestQueue().add(req);
45     }
46 
47     public ImageLoader getImageLoader() {
48         return mImageLoader;
49     }
50 }
複製代碼

 

四、Volley是怎麼管理請求的呢?   RequestQueue會維護一個緩存調度線程(cache線程)和一個網路調度線程池(net線程)(註意,這是一池子線程),當一個Request被加到隊列中的時候,cache線程會把這個請求進行篩選:如果這個請求的內容可以在緩存中找到,cache線程會親自解析相應內容,並分發到主線程(UI)。如果緩存中沒有,這個request就會被加入到另一個NetworkQueue,所有真正準備進行網路通信的request都在這裡,第一個可用的net線程會從NetworkQueue中拿出一個request扔向伺服器。當響應數據到的時候,這個net線程會解析原始響應數據,寫入緩存,並把解析後的結果返回給主線程。如下圖:   所以,讀源碼的話也可以把源碼分成四層,如下圖:(其餘的類都可以歸到“方便的工具類”中,比如ImageLoader,ClearCacheRequest等等)。
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在一些項目中,我們需要自定義自己的UIButton,使Button上面同時具有圖片和文字描述,實現自定義UIButton的圖文混排。 首先我們需要定義一個繼承自UIButton的類,同時實現自己的initWithFrame:方法。方法聲明在這個類的頭文件中。 self = [super initWi
  • category與associative作為objective c的擴展機制的兩個特性,category即類型,可以通過它來擴展方法;associative,可以通過它來擴展屬性;在iOS開發中,可能category比較常見,相對的associative,就用的比較少,要用它必須使用的頭文件,然後就
  • 經過前兩篇的介紹,我們瞭解瞭如何使用RoboGuice方便的為我們註入需要的對象,這篇將著重說明原理。 一.Guice與RoboGuice Guise是Google開發的一個輕量級的依賴註入框架,主要針對Java使用的。 RoboGuice是基於Guice庫開發,目的為Android提供一套簡單易用
  • 1.在java上面,public native void +方法名(""); 2.然後載入你需要的底層so文件system.loadLibrary("so文件名不能加尾碼") 3.然後在你需要調用native方法的時候,直接當做普通的方法調用 接下來就是在底層C或者C++上面的實現的 1.找到你項目
  • 代碼: - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. //寫法比較新奇 UIColor *bgColor =[UIColor redColor]; self.
  • 具體命令如下(在控制台輸入如下命令): lipo -create 其中一個要合併的靜態庫 另一個要合併的靜態庫 -output 合併後的靜態庫
  • 來自:http://www.cnblogs.com/nikyxxx/archive/2012/06/15/2551390.html 三個屬性都用來適應視圖的水平或垂直大小,一個以視圖的內容或尺寸為基礎的佈局比精確地指定視圖範圍更加方便。 1)fill_parent 設置一個構件的佈局為fill_pa
  • 昨天終於成功地向APP STORE提交了應用,個人感覺用AIR做IOS開發就是個坑啊。出了問題之後,問蘋果的技術支持,人家說“對於非XCODE環境下開發及發佈所造成的問題我們在資料庫中無法找到相應的解決方案”。那問adobe的技術支持吧,“你按照開發者中心的教程執行了嗎?”“是的”“你能成功生成IP
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...