Volley框架的使用

所謂Volley,它是2013年Google I/O上發佈的一款網絡框架,基於Android平臺,能使網絡通訊更快,更簡單,更健全。php

它的優勢:(1)默認Android2.3及以上基於HttpURLConnection,2.3如下使用基於HttpClient;(2)符合Http 緩存語義 的緩存機制(提供了默認的磁盤和內存等緩存);(3)請求隊列的優先級排序;(4)提供多樣的取消機制;(5)提供簡便的圖片加載工具(其實圖片的加載纔是咱們最爲看重的功能);(6)一個優秀的框架html

不足之處也有:它只適合數據量小,通訊頻繁的網絡操做,若是是數據量大的,像音頻,視頻等的傳輸,仍是不要使用Volley的爲好。android

 

1、得到Volleygit

能夠直接從google上git clone下來github

git clone https://android.googlesource.com/platform/frameworks/volley

而後生成jar包,導入到本身的項目中使用。注意,這個庫要求最低SDK版本爲Froyo,即至少要設置android:minSdkVersion爲8以上。json

不過因爲google的被牆,因此可能要FQ出去。嫌麻煩的話也能夠直接問我要jar包。緩存

 

2、使用Volley服務器

volley裏面自帶了不少的工具類,像StringRequest,JsonArrayRequest,JsonObjectRequest,ImageRequest這些都是咱們平時常用的http請求,咱們就能夠直接把它們拿過來用。如今來一一說明這些類的用法吧。cookie

在此以前,先說一下Volley中的requestQueue吧,全部的request申請出來後都是扔到這個隊列裏處理。網絡

requestQueue = Volley.newRequestQueue(context.getApplicationContext());
...
requestQueue.add(request);

這樣Volley就會幫你處理網絡通訊了。

(1)字符數據的處理

  1. StringRequest 網絡請求返回字符串
    StringRequest的網絡請求返回的是一個字符串。它有兩個構造函數
    /**
         * 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<String> 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<String> listener, ErrorListener errorListener) {
            this(Method.GET, url, listener, errorListener);
        }

    第二個構造函數相比第一個少了個method的參數,因此它是默認使用get方法。第一個構造函數是可讓咱們本身定義請求的方式,method的類型定義在Request類中

        /**
         * Supported request methods.
         */
        public interface Method {
            int DEPRECATED_GET_OR_POST = -1;
            int GET = 0;
            int POST = 1;
            int PUT = 2;
            int DELETE = 3;
            int HEAD = 4;
            int OPTIONS = 5;
            int TRACE = 6;
            int PATCH = 7;
        }

    默認是get,而除此之外咱們使用最多的是post的請求方法。

    Get請求:

            StringRequest request = new StringRequest(   
                    "http://www.baidu.com/",  
                    new Response.Listener<String>() {  
                        @Override  
                        public void onResponse(String arg0) {  //收到成功應答後會觸發這裏  
      
                        }  
                    },  
                    new Response.ErrorListener() {  
                        @Override  
                        public void onErrorResponse(VolleyError volleyError) { //出現鏈接錯誤會觸發這裏  
                           
    } } );

    在StringRequest中傳入一個url,一個通訊成功的觸發器和一個通訊失敗的觸發器。
    而post的請求方式以下:

               StringRequest request = new StringRequest(  
                        Request.Method.POST,  
                        "http://xxx.xxx.xxx",  
                        new Response.Listener<String>() {  
                            @Override  
                            public void onResponse(String s) {  
          
                            }  
                        },  
                        new Response.ErrorListener() {  
                            @Override  
                            public void onErrorResponse(VolleyError volleyError) {  
          
                            }  
                        }  
                ) {  
                    @Override  
                    public Map<String, String> getHeaders() throws AuthFailureError {  //設置頭信息  
                        Map<String, String> map = new HashMap<String, String>();  
                        map.put("Content-Type", "application/x-www-form-urldecoded");  
                        return map;  
                    }  
          
                    @Override  
                    protected Map<String, String> getParams() throws AuthFailureError {  //設置參數  
                        Map<String, String> map = new HashMap<String, String>();  
                        map.put("name", "cpacm");  
                        map.put("password", "12345");  
                        return map;  
                    }  
                };  

    能夠經過複寫裏面的方法把數據給傳進去,不止如此,若是還想對返回的數據進行進一步的處理,能夠在重寫下面這個方法

                /**
                 * 能夠對返回的reponse作處理, NetworkResponse裏面包括狀態碼,頭信息,內容數據,是否緩存在本地,花費的時間(ms)等內容
                 **/
                @Override
                protected Response<String> parseNetworkResponse(
                        NetworkResponse response) {
                    // 好比下面的例子是取頭信息裏的cookie數據
                    /*
                     * String mCookie; 
    * for (String s : response.headers.keySet()) { * if (s.contains("Set-Cookie")) { mCookie = * response.headers.get(s); break; } }
    */ return super.parseNetworkResponse(response); }

    與前面兩個重寫方法在通訊前調用不一樣,這個方法是在通訊結束後調用的。
    StringRequest的內容就那麼多,不是很理解的話能夠參考示例來仔細琢磨...

  2.  JsonObjectRequest json格式的數據通訊
    JsonArrayRequest是專對於jsonArray的處理,而JsonObjectRequest是對jsonObject的處理,因此兩個區別不大,因此我這裏就主要介紹JsonObjectRequest的使用。
    事實上,使用的方法和StringRequest並無什麼大的區別,觸類旁通嘛。

    JsonObjectRequest的構造函數也是有兩個,不過內容與StringRequest有一點不一樣。

    public JsonObjectRequest(int method, String url, JSONObject jsonRequest, Listener<JSONObject> listener, ErrorListener errorListener)  
      
    public JsonObjectRequest(String url, JSONObject jsonRequest, Listener<JSONObject> listener, ErrorListener errorListener) 

    第一個構造函數的參數分別爲 請求方法,url地址,附帶的jsonObject數據,成功監聽器,失敗監聽器。

    第二個構造函數比第一個少了method的參數,它默認的規則是:當jsonRequest爲空時,使用get請求方式,不爲空則是使用post方式。

    因爲構造函數中已經有了數據傳遞的參數,因此沒必要在重寫getParams()的方法了(重寫了也沒用)

    基本的調用方法:

    JsonObjectRequest request = new JsonObjectRequest(  
            "http://xxx.xxx.xx",  
            jsonObject,  
            new Response.Listener<JSONObject>() {  
                @Override  
                public void onResponse(JSONObject jsonObject) {  
      
                }  
            },  
            new Response.ErrorListener() {  
                @Override  
                public void onErrorResponse(VolleyError volleyError) {  
      
                }  
            }  
    ) {  
        @Override  
        public Map<String, String> getHeaders() throws AuthFailureError {  
            Map<String, String> map = new HashMap<String, String>();  
            map.put("Cookie", mCookie);  
            return map;  
        }  
    }; 

    最後只要再把成功監聽器裏拿到的數據處理就能使用了。

    post傳到服務器上時已是json格式,接着在服務器裏處理,返回的也要是json格式的數據,不然會致使數據錯誤(沒法轉化成JSONObject格式)。
    (!因此我用php寫的後臺來接受數據時,沒法用$_POST來接收上傳的數據)


    最後,別忘了把這些請求加到隊列中。

    requestQueue.add(request);

     

(2)圖片數據的處理

  1. ImageRequest 圖片請求
    ImageRequest與前面的request用法差很少,都是把請求扔到RequestQueue隊列裏。
    ImageRequest imageRequest = new ImageRequest(url,
                    new Listener<Bitmap>() {
    
                        @Override
                        public void onResponse(Bitmap bitmap) {
                            // TODO Auto-generated method stub    
                        }
    
                    }, maxWidth, maxHeight, decodeConfig, new ErrorListener() {
    
                        @Override
                        public void onErrorResponse(VolleyError arg0) {
                            // TODO Auto-generated method stub
                            Log.e(TAG, "ErrorStatus: " + arg0.toString());
                        }
                    });

    能夠看到,ImageRequest的構造函數能接收六個參數,第一個參數就是圖片的URL地址。第二個參數是圖片請求成功的回調, 這裏咱們能夠把返回的Bitmap參數設置到ImageView中。第三第四個參數分別用於指定容許圖片最大的寬度和高度,若是指定的網絡圖片的寬度或高度大於這裏的最大值,則會對圖片進行壓縮,指定成0的話就表示無論圖片有多大,都不會進行壓縮。第五個參數用於指定圖片的顏色屬性,Bitmap.Config下的幾個常量均可以在這裏使用,其中ARGB_8888能夠展現最好的顏色屬性,每一個圖片像素佔據4個字節的大小,而 RGB_565則表示每一個圖片像素佔據2個字節大小。第六個參數是圖片請求失敗的回調,這裏咱們能夠在請求失敗時在ImageView中顯示一張默認圖片。

    最後,把請求放入隊列中。
    requestQueue.add(request);
  2. ImageLoader 更增強大的網絡圖片請求
    ImageLoader也能夠用於加載網絡上的圖片,而且它的內部也是使用ImageRequest來實現的,不過ImageLoader明顯要比ImageRequest更加高效,由於它不只能夠幫咱們對圖片進行緩存,還能夠過濾掉重複的連接,避免重複發送請求。直接上代碼吧
            ImageLoader imageLoader = new ImageLoader(requestQueue,
                    new BitmapCache());//新建一個ImageLoader,傳入requestQueue和圖片緩存類
            ImageListener listener = ImageLoader.getImageListener(imageView,
                    default_image, failed_image);//參數分別爲要顯示的圖片控件,默認顯示的圖片(用於圖片未下載完時顯示),下載圖片失敗時顯示的圖片
            imageLoader.get(url, listener, maxWidth, maxHeight);//開始請求網絡圖片

    能夠看到,ImageLoader的構造函數接收兩個參數,第一個參數就是RequestQueue對象,第二個參數是一個ImageCache對象,咱們經過調用ImageLoader的getImageListener()方法可以獲取到一個ImageListener對象,getImageListener()方法接收三個參數,第一個參數指定用於顯示圖片的ImageView控件,第二個參數指定加載圖片的過程當中顯示的圖片,第三個參數指定加載圖片失敗的狀況下顯示的圖片。最後,調用ImageLoader的get()方法來加載圖片。

    圖片緩存類代碼以下:
    public class BitmapCache implements ImageCache {
    
        private LruCache<String, Bitmap> mCache;
    
        public BitmapCache() {
            int maxSize = 10 * 1024 * 1024;// 10M的緩存
            mCache = new LruCache<String, Bitmap>(maxSize) {
                @Override
                protected int sizeOf(String key, Bitmap bitmap) {
                    return bitmap.getRowBytes() * bitmap.getHeight();
                }
            };
        }
    
        @Override
        public Bitmap getBitmap(String url) {
            // TODO Auto-generated method stub
            return mCache.get(url);
        }
    
        @Override
        public void putBitmap(String url, Bitmap bitmap) {
            // TODO Auto-generated method stub
            mCache.put(url, bitmap);
        }
    
    }
  3. NetworkImageView 網絡圖片加載控件
    除了上面的兩種加載圖片之外,volley還提供了一個繼承ImageView的控件給咱們使用。咱們能夠把NetworkImageView控件放入佈局文件中而後就能調用了。
    <com.android.volley.toolbox.NetworkImageView   
            android:id="@+id/network_image_view"  
            android:layout_width="200dp"  
            android:layout_height="200dp"  
            android:layout_gravity="center_horizontal"  
            />

    先從佈局中得到控件的控制權,

    networkImageView = (NetworkImageView) findViewById(R.id.network_image_view);

    最後在設置一些相關的屬性

    networkImageView.setDefaultImageResId(R.drawable.default_image);  
    networkImageView.setErrorImageResId(R.drawable.failed_image);  
    networkImageView.setImageUrl(url,imageLoader);

    setImageUrl()方法接收兩個參數,第一個參數用於指定圖片的URL地址,第二個參數則是前面建立好的ImageLoader對象。其中的imageLoader須要咱們本身建立(就是上一個圖片加載方法的imageLoader),將其做爲參數傳進去。其實NetworkImageView控件和用ImageLoader加載圖片性質上都是同樣的。

     

(3)自定義數據的處理

自定義的網絡請求能夠繼承volley的Request類來重寫,好比說XML格式的請求。其中最重要的是Request類中的parseNetworkResponse方法。

像StringRequest中的parseNetworkResponse方法

        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));

 

重點是怎麼將response.data轉化成相應的字符格式。

像JsonObject裏面的方法

@Override
    protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
        try {
            String jsonString =
                new String(response.data, HttpHeaderParser.parseCharset(response.headers));
            return Response.success(new JSONObject(jsonString),
                    HttpHeaderParser.parseCacheHeaders(response));
        } catch (UnsupportedEncodingException e) {
            return Response.error(new ParseError(e));
        } catch (JSONException je) {
            return Response.error(new ParseError(je));
        }
    }

先將傳過來的數據轉化成String格式,再根據狀況轉成Json或者是XML。

如咱們自定義的XMLRequest能夠寫成這樣子。

@Override
    protected Response<XmlPullParser> 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));
        }
    }

 

 

3、結束語

Volley給咱們在網絡傳輸的方面提供了很大的方便,尤爲是網絡圖片加載的部分。除此以外,咱們能夠從volley的源代碼入手能夠學習到更多的知識,好比說如何構建一個完善的框架,如何使框架具備良好的擴展性。因此我建議有空的話能夠把源代碼下載過來仔細體味一番...

源碼的分析在下面的文章連接中。

 

參考文章:(1) Android Volley徹底解析 http://blog.csdn.net/guolin_blog/article/details/17482095

               (2)Android應用開發:網絡工具——Volley(一) http://blog.csdn.net/airk000/article/details/38983051

         (3)Android應用開發:網絡工具——Volley(二) http://blog.csdn.net/airk000/article/details/39003587

               (4)github上的volley庫分析 https://github.com/android-cn/android-open-project-analysis/tree/master/volley

Demo地址:這是github上一個開源分析項目(@android-cn)裏面一位成員(@grumoon包括上面的volley庫分析)所寫的一個volley demo地址 https://github.com/android-cn/android-open-project-demo/tree/master/volley-demo

========================================

 

做者:cpacm

地址:http://www.cnblogs.com/cpacm/p/4193011.html

相關文章
相關標籤/搜索