Volley使用技巧-----更好的封装(cookie的使用)

来源:互联网 发布:程序员的思维修炼 pdf 编辑:程序博客网 时间:2024/05/16 11:03

Volley使用技巧—–更好的封装(cookie的使用)

题外话

上一篇讲到如何自定义Request以便更方便的使用Volley,这篇即将分享的是如何更好用进行封装,使volley使用起来更加的方便,简单,顺便带上了关于cookie的处理方法.

正题

回顾上一篇博客中提到使用volley最初步骤,即创建一个请求队列:

mQueue = new Volley.RequestQueue(getApplicationContext());

这样的话每到一个activity或者fragment中,就不得不去重新创建一个队列,每个队列的生命周期也跟随着activity或者fragment,为了避免这种繁琐的情况,可以自定义一个工具类,其中持有一个队列,这个队列的生命周期跟随整个应用.

搜寻了一下,发现android应用在创建的时候会有一个application类实例跟随着产生,如果对Application类不是很熟悉的话,可以参考这篇博客.下面是自定义出来的application类:

public class RequestQueueController extends Application{  //关于cookie的关键字  private static final String SET_COOKIE_KEY = "Set-Cookie";  private static final String COOKIE_KEY = "Cookie";  private static final String COOKIE_USERNAME = "username";  //请求队列  private RequestQueue _requestQuene;  //SharedPreferences,用于存储少量的数据  private SharedPreferences _preferences;  //本类的实例  private static RequestQueueController _instance;  public static RequestQueueController get() {    return _instance;  }  /**   * 该方法在应用运行的时候就会自动调用   */  @Override  public void onCreate() {    super.onCreate();    _instance = this;    _preferences = getSharedPreferences(AppConstant.PREFERENCE_NAME,0);    _requestQuene = Volley.newRequestQueue(this);  }  /**   * 返回请求队列   * @return   */  public RequestQueue getRequestQueue() {    return _requestQuene;  }  /**   * 用于检测返回头中包含的cookie   * 并且更新本地存储的cookie   * @param headers   */  public final void checkSessionCookie(Map<String, String> headers) {    if (headers.containsKey(SET_COOKIE_KEY)) {      String cookie = headers.get(SET_COOKIE_KEY);      if((cookie.length()) > 0 && (!cookie.contains("saeut"))) {        String[] splitCookie = cookie.split(";");        String[] splitSessionId = splitCookie[0].split("=");        cookie = splitSessionId[1];        SharedPreferences.Editor prefEditor = _preferences.edit();        prefEditor.putString(COOKIE_USERNAME, cookie);        prefEditor.apply();      }    }  }  /**   * 向请求头中加入cookie   * @param headers   */  public final void addSessionCookie(Map<String, String> headers) {    String sessionId = _preferences.getString(COOKIE_USERNAME, "");    if (sessionId.length() > 0) {      StringBuilder builder = new StringBuilder();      builder.append(COOKIE_USERNAME);      builder.append("=");      builder.append(sessionId);      if (headers.containsKey(COOKIE_KEY)) {        builder.append("; ");        builder.append(headers.get(COOKIE_KEY));      }      headers.put(COOKIE_KEY, builder.toString());    }  }}

上面的自定义类继承了Application类,记住还需要在AndroidManifest.xml中的Application标签中加入RequestQueueController(自定义类名),将这个自定义类和Application绑定到一起,就可以在应用启动的时候执行onCreate()方法中的代码了;

处理好了请求队列的创建之后,再来分析request,之前使用request都是直接创建两个listener来处理,写在一起会让代码看上去冗余,就类似这样:

request.setOnClickListener(new View.OnClickListener() {      @Override      public void onClick(View view) {        //处理请求成功返回的结果        Response.Listener<String> listener = new Response.Listener<String>() {          @Override          public void onResponse(String s) {            Log.e("dada", s);          }        };        //处理请求错误返回的结果        Response.ErrorListener errorListener = new Response.ErrorListener() {          @Override          public void onErrorResponse(VolleyError volleyError) {            Log.e("error", volleyError.toString());          }        };        //实例化请求对象        StringRequest stringRequest = new StringRequest("http://www.baidu.com", listener, errorListener);        //向队列中加入请求        requestQueue.add(stringRequest);        requestQueue.start();      }    });

可以模仿Angularjs那种模式来将这些分层,大致分为三层:

  1. 最底层的API,负责创建Request并加入请求队列,根据返回值的需求不同来封装.供第二层来调用.
  2. 将最顶层传入的信息传给最底层的API,并将请求返回的信息处理(根据自己的情况来处理),通过回调接口传递给顶层的调用者.
  3. 顶层的调用者只需要给出相应的第二层调用和相关参数,其余可以不用管理.

经过上面三层的分离之后,每一层都有明确的分工,而且互不干扰,更方便开发者调用,下面给出上面三层的代码(封装了JSONArrayRequestPlus的API,其余的是相同的道理):

/** * 最底层的API * 只根据传来的参数创建了Request * 并将其加入了队列中 */public class HttpApi {  /**   * 返回JsonArray的网络请求Api   * @param method   * @param url   * @param requestBody   * @param listener   * @param errorListener   */  public static void DoJsonArrayRequest(int method,                                        String url,                                        HashMap hashMap,                                        Response.Listener<JSONArray> listener,                                        Response.ErrorListener errorListener) {    final HashMap<String,String> map = hashMap;    try{      JsonArrayRequestPlus jsonArrayRequestPlus = new JsonArrayRequestPlus(method, url, listener, errorListener){        @Override        protected Map<String, String> getParams() throws AuthFailureError {          return map;        }      };     RequestQueueController.get().getRequestQueue().add(jsonArrayRequestPlus);    } catch (Exception e) {      e.printStackTrace();    }  }}

最底层的API弄好之后,第二层就对其直接调用,也就是第三层调第二层,第二层调第一层,返回结果给第二层做处理,再回传需要的结果给顶层的调用者.

/** * 第二层相当与传输层 * 也负责了对数据进行处理 */public class HttpService {  /**   * 登录请求   *///自持有一个接口,这个接口就是用来传递结果的,接口的定义就在下面一行,两个函数分别对应着Volley给出的两个接口  private static OnLoginRequestResponseListener mLoginRequestListener;  public static interface OnLoginRequestResponseListener {    public void OnLoginSuccessResponse(JSONArray jsonArray);    public void OnLoginErrorResponse(String errorResult);  }  public static void DoLoginRequest (int method,                                     String url,                                     HashMap<String,String> hashMap,                                     OnLoginRequestResponseListener listener  ) {    mLoginRequestListener = listener;    Response.Listener<JSONArray> responseListener = new Response.Listener<JSONArray>() {      @Override      public void onResponse(JSONArray jsonArray) {        mLoginRequestListener.OnLoginSuccessResponse(jsonArray);      }    };    Response.ErrorListener errorListener = new Response.ErrorListener() {      @Override      public void onErrorResponse(VolleyError volleyError) {        mLoginRequestListener.OnLoginErrorResponse(volleyError.getMessage());      }    };    HttpApi.DoJsonArrayRequest(method, url, hashMap, responseListener, errorListener);  }  /**   * 注册请求   *///这个类似于上面的,调用的是同一个底层的接口,一次封装多次调用,很方便  private static OnSignupRequestResponseListener mSignupRequestListener;  public static interface OnSignupRequestResponseListener {    public void OnSignupSuccessResponse(JSONArray jsonArray);    public void OnSignupErrorResponse(String errorResult);  }  public static void DoSignupRequest (int method,                                      String url,                                      HashMap<String, String> hashMap,                                      OnSignupRequestResponseListener listener  ) {    mSignupRequestListener = listener;    Response.Listener<JSONArray> responseListener = new Response.Listener<JSONArray>() {      @Override      public void onResponse(JSONArray jsonArray) {        mSignupRequestListener.OnSignupSuccessResponse(jsonArray);      }    };    Response.ErrorListener errorListener = new Response.ErrorListener() {      @Override      public void onErrorResponse(VolleyError volleyError) {        mSignupRequestListener.OnSignupErrorResponse(volleyError.getMessage());      }    };    HttpApi.DoJsonArrayRequest(method, url, hashMap, responseListener, errorListener);  }}

第二层弄完了之后,第三层就剩下实现回调接口以及调用了,实现的代码如下:

public class MainActivity extends ActionBarActivity         implements HttpService.OnLoginRequestResponseListener{  //提交请求的按钮  private Button request;  @Override  protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    request.setOnClickListener(new View.OnClickListener() {      @Override      public void onClick(View view) {        HttpService.DoLoginRequest(Request.Method.POST,url,map,MainActivity.this);      }    });  }//后面这两个重写的方法就是第二层中需要调用的回调方法,在这里接收到信息后做出响应,这里没有给出具体的处理代码  @Override  public void OnLoginSuccessResponse(JSONArray jsonArray) {  }  @Override  public void OnLoginErrorResponse(String errorResult) {  }}

关于cookie

在开头的自定义Application类中已经定义了两个方法,就是存取cookie值的方法,只需要在自定义的request中加入这两个方法就可以了,相关加入位置如下:

public class JsonArrayRequestPlus extends Request<JSONArray>{  private final Response.Listener<JSONArray> mListener;  public JsonArrayRequestPlus(int method,                              String url,                              Response.Listener<JSONArray> listener,                              Response.ErrorListener errorListener) {    super(method, url, errorListener);    mListener = listener;  }//重写getHeader()方法,请求会自动调用这个方法来获取请求头部,所以我们将本地的cookie存放进一个map返回回去,cookie就会包含到header里面去  @Override  public Map<String, String> getHeaders() throws AuthFailureError {    Map<String, String> headers = super.getHeaders();    if(headers == null || headers.equals(Collections.emptyMap())) {      headers = new HashMap<>();    }//这个方法就是自定义Application类中添加cookie的方法RequestQueueController.get().addSessionCookie(headers);    return headers;  }  @Override  protected void deliverResponse(JSONArray jsonArray) {    mListener.onResponse(jsonArray);  }  @Override  protected Response<JSONArray> parseNetworkResponse(NetworkResponse response) {//在处理返回信息的时候,服务器会返回cookie,在这里截取到cookie并且存储到本地RequestQueueController.get().checkSessionCookie(response.headers);    try {      String jsonString =              new String(response.data, HttpHeaderParser.parseCharset(response.headers));      return Response.success(new JSONArray(jsonString),              HttpHeaderParser.parseCacheHeaders(response));    } catch (UnsupportedEncodingException e) {      return Response.error(new ParseError(e));    } catch (JSONException je) {      return Response.error(new ParseError(je));    }  }}

关于这些如果还有什么不明白的,可以直接给小达留言,或者直接加QQ2319821734,希望能和大家相互学习交流,共同进步~今天就到这里咯,晚安~

0 0
原创粉丝点击