android Volley解析之自定義CookieObjectRequest

      以前項目中涉及到Http請求時,一直用的是開源項目asncclient,封裝的非常好,使用起來也非常的方便,不再需要自己去管理線程的生命週期,只需要創建一個請求,寫一個請求回調即可,13年,google推出了velloy請求框架,功能基本與asyncclient 一樣,都是爲了簡化網絡請求編程,但更加靈活,用戶可以根據需求自定義不同的請求,關於 Velloy的基本用法就不在說了,網上有許多教程,今天的文章主要講一下,如何自定義一個帶Cookie的並且直接返回Object類型的Request .這一類型的請求也一定是程序 中最常用 的.

   先看一下,Velloy村身爲我們提供了那些請求類型:

    1.StringRequest,專門用來處理String類型的數據請求;

     2.JsonObjectRequest和JsonArrayRequest,專門用來處理Json對象類型的數據請求

     顯然,Velloy自帶的這幾請求類型並不是我們程序中最常用的,無論是返回JsonObject還是String,都需要我們二次處理爲對象類型,那麼可不可以有一個請求返回的直接就是我們需要的 Entity對象呢,當然是可以的,其次,Velloy爲我們提供的請求 都是無Cookie管理的,這顯然也是不 完整的.

      基於以上兩點原因,我們自定義一個再Cookie管理的,直接返回Entity對象的Request.先看一下StringRequest類的源碼,源碼如下:   

    public class StringRequest extends Request<String> {  
        private final Listener<String> mListener;  
      
        public StringRequest(int method, String url, Listener<String> listener,  
                ErrorListener errorListener) {  
            super(method, url, errorListener);  
            mListener = listener;  
        }  
      
        public StringRequest(String url, Listener<String> listener, ErrorListener errorListener) {  
            this(Method.GET, url, listener, errorListener);  
        }  
      
        @Override  
        protected void deliverResponse(String response) {  
            mListener.onResponse(response);  
        }  
      
        @Override  
        protected Response<String> 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));  
        }  
    }  
      源碼很簡單,我們需要注意的也就是parseNetworkResponse這個方法,它是處理服務器返回數據的核心方法,在StringRequest 類的處理中,就是拿到響應體的數據,再根據頭中的請求編碼格式,轉化爲一個字符串,所以我們只要在此方法中將返回 的數據轉化爲我們需要的對象類型既可.下面看代碼:    

     

    public class ObjectRequest extends Request<Object> {  
      
            //請求成功回調  
        private final Listener<Object> mListener;  
            //實體對象字節碼  
            private final Class<?> clazz;  
            //請求參數列表  
            private final HashMap<String, String> paramsMap;  
      
        public ObjectRequest(String url, HashMap<String, String> paramsMap,  
                Listener<Object> listener, ErrorListener errorListener,  
                Class<?> clazz) {  
            super(Method.POST, url, errorListener);  
            this.mListener = listener;  
            this.clazz = clazz;  
            this.paramsMap = paramsMap;  
        }  
      
        /** 
         * 添加請求頭部信息 
         */  
        @Override  
        public Map<String, String> getHeaders() throws AuthFailureError {  
                    //<span style="color:#FF0000;">如果Application中已經有了Cookie信息,帶Cookie請求.</span>  
            Map<String, String> map = new HashMap<String, String>();  
            if (VolleyApplication.getInstance().getCookie() != null) {  
                map.put("Cookie", VolleyApplication.getInstance().getCookie());  
            }  
            return super.getHeaders();  
        }  
      
        /** 
         * 添加請求參數方法 
         */  
        @Override  
        protected Map<String, String> getParams() throws AuthFailureError {  
            return paramsMap;  
        }  
      
        @Override  
        protected Response<Object> parseNetworkResponse(NetworkResponse response) {  
      
            for (String s : response.headers.keySet()) {  
                if (s.contains("Set-Cookie")) {  
                    /** 
                     *<span style="color:#FF0000;"> 保存到全局Cookie變量中,後續的請求直接取出使用</span> 
                     */  
                    VolleyApplication.getInstance().setCookie(  
                            response.headers.get(s));  
                    break;  
                }  
            }  
      
            try {  
                String string = new String(response.data,  
                        HttpHeaderParser.parseCharset(response.headers));  
                            /<span style="color:#FF0000;">/將返回的Json字符串直接轉化爲對象</span>  
                return Response.success(  
                        ResponseEntityToModule.parseJsonToModule(string, clazz),  
                        HttpHeaderParser.parseCacheHeaders(response));  
            } catch (UnsupportedEncodingException e) {  
                return Response.error(new ParseError(e));  
            } catch (Exception e) {  
                return Response.error(new ParseError(e));  
            }  
        }  
      
        @Override  
        protected void deliverResponse(Object response) {  
            mListener.onResponse(response);  
        }  
      
    }  
      
  很簡單的我們就定製了一個直接返回對象並且處理了Cookie 的請求對象.下面看如何使用它去請求服務器.     

  1.Activity中代碼:  

    public class MainActivity extends Activity implements Listener<Object>,  
            ErrorListener {  
      
        @Override  
        protected void onCreate(Bundle savedInstanceState) {  
            super.onCreate(savedInstanceState);  
            setContentView(R.layout.activity_main);  
      
            RequestCenter.getInstance().userLogin("focusgbbuyer", "focus1234",  
                    this, this);  
        }  
      
        @Override  
        public void onErrorResponse(VolleyError error) {  
            // TODO Auto-generated method stub  
      
        }  
      
        @Override  
        public void onResponse(Object response) {  
            Log.e("Response", "Session:"+((User) response).sessionid + "\r\nCookie:"  
                    + VolleyApplication.getInstance().getCookie());  
        }  
      
    }  
   2.RequestCenter中是所有請求的集合: 

   

    public class RequestCenter {  
      
        private static RequestCenter instance = null;  
        private RequestQueue mQueue;  
        private VolleyApplication application;  
      
        private RequestCenter() {  
            application = VolleyApplication.getInstance();  
            mQueue = application.getRequestQueue();  
        }  
      
        public static RequestCenter getInstance() {  
      
            if (instance == null) {  
      
                synchronized (RequestCenter.class) {  
                    if (instance == null) {  
                        instance = new RequestCenter();  
                    }  
                }  
            }  
            return instance;  
        }  
      
        /** 
         * 用戶登錄請求 
         *  
         * @param username 
         *            用戶名 
         * @param password 
         *            密碼 
         * @param context 
         * @param lisener 
         *            登錄結果回調 
         */  
        public void userLogin(String username, String password,  
                Listener<Object> listener, ErrorListener errorListener) {  
            HashMap<String, String> params = new HashMap<String, String>();  
            params.put("loginId", username);  
            params.put("password", password);  
            params.put("region", "MIC for Buyer Android");  
      
            ObjectRequest stringRequest = new ObjectRequest(  
                    UrlConstants.USER_LOGIN, params, listener, errorListener,  
                    User.class);  
            mQueue.add(stringRequest);  
        }  
    }  

           使用單例確保這些大對象,只有一個實例既可.經過這樣一封裝,使用起來很簡單了.下面看服務器的返回數據.


        

           好了,完全符合我們的要求,有新需求還可以在上面直接修改,下面是Demp源碼:

           VolleyDemo源碼

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