Android Volley:使用方法總結及實例解析

一、概述

1. Volley谷歌官方翻譯教程

  1. 使用Volley傳輸網絡數據
    Volley 是一個HTTP庫,它能夠幫助Android apps更方便的執行網絡操作,最重要的是,它更快速高效。可以通過開源的 AOSP 倉庫獲取到Volley 。

  2. 發送簡單的網絡請求 (Sending a Simple Request)
    學習如何通過Volley默認的行爲發送一個簡單的請求,以及如何取消一個請求。

  3. 建立請求隊列 (Setting Up a RequestQueue)
    學習如何建立一個請求隊列,以及如何實現一個單例模式來創建一個請求隊列,使RequestQueue能夠持續保持在你的app的生命週期中。

  4. 創建標準的網絡請求 (Making a Standard Request)
    學習如何使用Volley的out-of-the-box(可直接使用、無需配置)的請求類型(raw strings, images, and JSON)來發送一個請求。

  5. 實現自定義的網絡請求 (Implementing a Custom Request)
    學習如何實現一個自定義的請求,比如 GsonRequest 。

  6. Gson in GitHub

  7. Volley in GitHub
for Gradle:
    compile 'com.mcxiaoke.volley:library:1.0.19'

2. 基於官方教程的一些細節筆記

  1. Volley使用方式:通過創建一個RequestQueue並傳遞Request對象給它。
  2. RequestQueue:管理用來執行網絡操作的工作線程,從Cache中讀寫數據,並解析Http的響應內容
    • 請求隊列:可以緩存所有的HTTP請求,然後按照一定的算法併發地發出這些請求。
  3. Requests:執行raw responses的解析,Volley會把響應的數據分發給 主線程

  4. Volley總是將解析後的數據返回至主線程中
    在主線程中更加合適使用接收到的數據用來操作UI控件,這樣你可以在響應的handler中輕鬆的修改UI。

  5. 你可以在任何線程中添加一個請求,但是響應結果都是返回到主線程的
    注意那:耗時的操作,例如I/O與解析parsing/decoding都是執行在工作線程。

  6. 一個請求的生命週期:
    這裏寫圖片描述

  7. 對Request對象調用cancel()方法:取消一個請求

    • 一旦取消,Volley會確保你的響應Handler不會被執行。
    • 這意味着在實際操作中你可以在activity的onStop()方法中取消所有pending在隊列中的請求(通過 stringRequest.setTag(TAG); 中的Tag)。
  8. 創建一個單例的RequestQueue,這使得RequestQueue能夠持續保持在你的app的生命週期中。

    • 對於ImageLoade來說,單例模式可以避免旋轉所帶來的抖動。
    • 使用單例模式可以使得bitmap的緩存與activity的生命週期無關。
    • 如果你在activity中創建ImageLoader,這個ImageLoader有可能會在手機進行旋轉的時候被重新創建。這可能會導致抖動
  9. Volley 的設計目標: 非常適合去進行數據量不大,但通信頻繁的網絡操作
    對於大數據量的網絡操作,比如說下載文件等,Volley的表現就會非常糟糕。

二、使用方法

1. 創建Volley 單例

public class MyApp extends Application {

    public static final String TAG = MyApp.class.getSimpleName();
    private RequestQueue mRequestQueue;
    private ImageLoader mImageLoader;

    private static MyApp mInstance;

    @Override
    public void onCreate() {
        super.onCreate();
        mInstance = this;
    }

    public static synchronized MyApp getInstance() {
        return mInstance;
    }

    public RequestQueue getRequestQueue() {
        if (mRequestQueue == null) {
            mRequestQueue = Volley.newRequestQueue(getApplicationContext());
        }
        return mRequestQueue;
    }

    public ImageLoader getImageLoader() {
        getRequestQueue();
        if (mImageLoader == null) {
            mImageLoader = new ImageLoader(mRequestQueue, new LruBitmapCache());
        }
        return mImageLoader;
    }

    public <T> void addToRequestQueue(Request<T> request,String tag) {
        request.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
        getRequestQueue().add(request);
    }

    public <T> void addToRequestQueue(Request<T> request) {
        request.setTag(TAG);
        getRequestQueue().add(request);
    }

    public void cancelPendingRequests() {
        if (mRequestQueue != null) {
            mRequestQueue.cancelAll(TAG);
        }
    }

}

2. 需要一個Cache來緩存請求的圖片:

public class LruBitmapCache extends LruCache<String, Bitmap> implements ImageLoader.ImageCache {

    public static int getDefaultLruCacheSize() {
        final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
        final int cacheSize = maxMemory / 8;

        return cacheSize;
    }

    public LruBitmapCache(int maxSize) {
        super(maxSize);
    }

    public LruBitmapCache() {
        this(getDefaultLruCacheSize());
    }

    @Override
    protected int sizeOf(String key, Bitmap value) {
        return value.getRowBytes() * value.getHeight() / 1024;
    }

    @Override
    public Bitmap getBitmap(String url) {
        return get(url);
    }

    @Override
    public void putBitmap(String url, Bitmap bitmap) {
        put(url, bitmap);
    }
}

三、GET請求

1. 創建json object請求

發送一個請求只要這麼簡單:

  • 創建一個JsonRequest對象,寫好response回調接口
  • 把這個請求放到請求隊列中就可以了。

JsonArrayRequest也類似。

2. 創建String請求

  • StringRequest 可以用來請求任何string類型的數據jsonxml文本

3. 小結

  • StringRequest,JsonRequest都是繼承自Request類的
  • 不過由於JsonRequest是一個抽象類,我們無法直接創建它的實例,
    只能通過它兩個直接的子類 JsonObjectRequestJsonArrayRequest 入手。

四、POST請求

1. 創建POST請求

與GET請求不同的是:

  • 只要在創建請求的時候將請求類型改爲POST請求 : Method.POST
  • 並且重寫Request的 getParams() 方法即可。
        @Override
        protected Map<String, String> getParams() {
            Map<String, String> params = new HashMap<String, String>();
            params.put("name", "Androidhive");
            params.put("email", "[email protected]");
            params.put("password", "password123");

            return params;
        }

2. 添加請求頭部信息

  • 重寫 getHeaders() 方法 。
        /**
        * Passing some request headers
        * */
        @Override
        public Map<String, String> getHeaders() throws AuthFailureError {
            HashMap<String, String> headers = new HashMap<String, String>();
            headers.put("Content-Type", "application/json");
            headers.put("apiKey", "xxxxxxxxxxxxxxx");
            return headers;
        }

五、Image請求

1. 用NetworkImageView加載圖片

Volley庫中自帶了NetworkImageView類,這個ImageView可以 自動 使用volley下載圖片。

原理:

  • NetworkImageView加載圖片需要一個ImageLoader和一個圖片URL
    這個ImageLoader對象需要一個請求隊列對象ImageCahe對象

  • 調用NetworkImageView的setUrl()方法後,首先會判斷當前ImageView的URL和新傳入的URL是否一致,

    • 如果相同,就不用再發送http請求了,
    • 如果不同,那麼就使用ImageLoader對象來發送http請求獲取圖片。
ImageLoader imageLoader = MyApp.getInstance().getImageLoader();
// If you are using NetworkImageView
imgNetWorkView.setImageUrl(Const.URL_IMAGE, imageLoader);

2. 用 ImageLoader 和 ImageView來加載圖片

ImageLoader imageLoader = MyApp.getInstance().getImageLoader();

// If you are using normal ImageView
imageLoader.get(Const.URL_IMAGE, new ImageListener() {

    @Override
    public void onErrorResponse(VolleyError error) {
        // 設置爲出錯的圖片
    }

    @Override
    public void onResponse(ImageContainer response, boolean arg1) {
        if (response.getBitmap() != null) {
            // load image into imageview
            imageView.setImageBitmap(response.getBitmap());
        }
    }
});
  • 也可以再簡單一點:
// Loading image with placeholder and error image
imageLoader.get(Const.URL_IMAGE, 
    ImageLoader.getImageListener(imageView, 
        R.drawable.ico_loading, R.drawable.ico_error));
  • ImageLoader.getImageListener() 方法中已經寫了一個默認的ImageListener了。

2. 用 ImageRequest 和 ImageView來加載圖片

   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的構造函數接收六個參數:

  1. 圖片的URL地址
  2. 圖片請求成功的回調:
    這裏我們把返回的Bitmap參數設置到ImageView中
  3. 允許圖片最大的寬度
  4. 允許圖片最大的高度:
    如果指定的網絡圖片的寬度或高度大於這裏的最大值,則會對圖片進行壓縮,指定成0的話就表示不管圖片有多大,都不會進行壓縮。
  5. 指定圖片的顏色屬性:
    Bitmap.Config下的幾個常量都可以在這裏使用,其中ARGB_8888可以展示最好的顏色屬性,每個圖片像素佔據4個字節的大小,而RGB_565則表示每個圖片像素佔據2個字節大小。
  6. 圖片請求失敗的回調:
    這裏我們當請求失敗時在ImageView中顯示一張默認圖片。

六、Volley Cache

volley中自帶了強大的cache機制來管理請求cache,這會減少網絡請求次數和用戶等待時間。

1. 從請求Cache中加載請求

Cache cache = MyApp.getInstance().getRequestQueue().getCache();
Entry entry = cache.get(url);
if(entry != null){
    try {
        String data = new String(entry.data, "UTF-8");
        // handle data, like converting it to xml, json, bitmap etc.,
    } catch (UnsupportedEncodingException e) {      
        e.printStackTrace();
        }
    }
}else{
    // Cached response doesn't exists. Make network call here
}

2. 使請求緩存失效

  • 失效並不意味這刪除,
  • Volley還會繼續使用緩存的對象直到從服務器上獲取到了新的數據,
  • 新的數據會覆蓋舊的數據。
MyApp.getInstance().getRequestQueue().getCache().invalidate(url, true);

3. 關閉Cache

  • 如果你想將某一個請求的Cache功能關閉,
  • 直接調用Request的setShouldCache() 方法就可以:
// String request
StringRequest stringReq = new StringRequest(....);

// disable cache
stringReq.setShouldCache(false);

4. 將某一URL的Cache刪除

  • 調用Cache的 remove() 方法可以刪除這個URL的cache:
MyApp.getInstance().getRequestQueue().getCache().remove(url);

5. 刪除所有的Cache

  • 使用Cache的 clear() 方法:
MyApp.getInstance().getRequestQueue().getCache().clear();

6. 取消請求

在添加請求到請求隊列中的時候,可以現,
addToRequestQueue(request, tag)方法還接受一個tag參數,
這個tag就是用來標記某一類請求的,這樣就可以取消這個tag的所有請求了:

static final String TAG = "json_req";
MyApp.getInstance().getRequestQueue().cancelAll(TAG);

七、請求優先級

在創建一個request時
可以重寫 Request方法的getPriority() 方法返回一個優先級,
優先級分爲:Normal, Low, HighImmediate

    private Priority priority = Priority.HIGH;

    StringRequest strReq = new StringRequest(Method.GET,
            Const.URL_STRING_REQ, new Response.Listener<String>() {

                @Override
                public void onResponse(String response) {
                    Log.d(TAG, response.toString());
                    msgResponse.setText(response.toString());
                    hideProgressDialog();

                }
            }, new Response.ErrorListener() {

                @Override
                public void onErrorResponse(VolleyError error) {
                    VolleyLog.d(TAG, "Error: " + error.getMessage());
                    hideProgressDialog();
                }
            }) {
        @Override
        public Priority getPriority() {
            return priority;
        }

    };

參考文章:
1. Android庫Volley的使用介紹
2. Android Volley完全解析(二),使用Volley加載網絡圖片
3. Android Volley完全解析(三),定製自己的Request
4. Android Volley完全解析(四),帶你從源碼的角度理解Volley

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章