Android.Volley的解读:request

这文章是用来记录自己最近使用volley的StringRequest的一些心得,以及volley关于request的代码深读。

从网络上可以知道,volley适合数据量不大但是通信频繁的场景。volley提供的便利功能有如下这些:

  • JSON,图像等的异步下载;
  • 网络请求的排序(scheduling)
  • 网络请求的优先级处理
  • 缓存
  • 多级别取消请求
  • 和Activity和生命周期的联动(Activity结束时同时取消所有网络请求)

从一些网络前辈和自己使用的情况来说,volley的图片处理并不是最佳,我选择了Picasso,所以我只用到了request,以及和Activity生命周期的联动两个特性。

之前写了一篇volley的初接触,主要是Volley.newRequestQueue(getApplicationContext());这句代码的解读。

以下开始解读StringRequest。

网络上的前辈都把StringRequest请求当做自定义请求,和JsonObjecy JsonArray 区别开,我也不清楚为什么要这样区别,暂且没用过volley的json请求,但是看过介绍,感觉所有的request都差不多。

使用情景,利用StringRequest请求解析一段xml数据。

StringRequest request = new StringRequest(
    Request.Method.GET,
    Contants.HTTP_SERVER + Contants.HTTP_TABS,
    new Response.Listener<String>(){
    @Override
    public void onResponse(String response){
      //这里处理请求返回的response
      ... ...
    }
  }, new Response.ErrorListener(){
    @Override
    public void onErrorResponse(VolleyError error){
      //这里处理请求失败的工作
      LogUtils.d(TAG,error.toString());
    }
  }
);

还是一句代码,所有用到的参数都出现了,现在到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);    //这里是调用super 不是 this
        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);    //设置我们的listener
    }

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

StringRequest类的代码不多,但都是重要的组成部分。

这里记录自己当初的两个惑点super(method, url, errorListener) 和 parseNetworkResponse & mListener.onResponse(response)的区别。

首先是super(method, url, errorListener) :StringRequest继承Request<String>,跳转到Request<String>中

    public Request(int method, String url, Response.ErrorListener listener) {
        mMethod = method;
        mUrl = url;
        mErrorListener = listener;
        setRetryPolicy(new DefaultRetryPolicy());

        mDefaultTrafficStatsTag = findDefaultTrafficStatsTag(url);
    }

Request中保存了提交方式,连接的url,错误监听接口,并设置了重试策略,而且从url中找到通信状态标志(有什么用?)

设置重试策略感觉很好理解,看看DefaultRetryPolicy类就知道七八分了,作用大概就是设置url连接的失败重试的一些属性(我自己脑补的-_-!!!)

    public DefaultRetryPolicy() {
        this(DEFAULT_TIMEOUT_MS, DEFAULT_MAX_RETRIES, DEFAULT_BACKOFF_MULT);
    }

    ...
    /**
     * Constructs a new retry policy.
     * @param initialTimeoutMs The initial timeout for the policy.
     * @param maxNumRetries The maximum number of retries.
     * @param backoffMultiplier Backoff multiplier for the policy.
     */
    public DefaultRetryPolicy(int initialTimeoutMs, int maxNumRetries, float backoffMultiplier) {
        mCurrentTimeoutMs = initialTimeoutMs;
        mMaxNumRetries = maxNumRetries;
        mBackoffMultiplier = backoffMultiplier;
    }

剩下的mDefaultTrafficStatsTag = findDefaultTrafficStatsTag(url);函数的javadoc里解释返回The hashcode of the URL's host component, or 0 if there is none,这下就不太好脑补了,还是先看看函数的实现。

    private static int findDefaultTrafficStatsTag(String url) {
        if (!TextUtils.isEmpty(url)) {
            Uri uri = Uri.parse(url);
            if (uri != null) {
                String host = uri.getHost();
                if (host != null) {
                    return host.hashCode();
                }
            } 
        }
        return 0;
    }

看到出奇简单的代码,我联想到了volley的缓存机制,听说是简单的判断url是否相同,难道就是这个??是不是这个也不重要了,反正StringRequest的初始化属性如上。

剩下就是deliverResponse和parseNetworkResponse,然后从网络上找到了一篇说得比较清楚得文章

http://www.apihome.cn/view-detail-70213.html

我用自己的白话文归纳一下:parseNetworkResponse是用于特定类型(String、Json、JsonArray、Image)请求的解析,把服务端返回的数据解析成指定类型,然后系统回调deliverResponse派发相应的实例当中。不太明白可以看看以上类型对应的Request,里面都用parseNetworkResponse把NetworkResponse转变成相应类型。

Note:在我没写这篇文章前,我都是直接在初始化StringRequest请求的时候,我都没有重写parseNetworkResponse,直接拿到服务端的原始string,然后在Response.listener中的onResponse中进行处理,感觉不太native。感谢网络上的前辈,感谢自己。

补充一张超大图。是我自己画的volley工作视图,请下载放大查看。

原文地址:https://www.cnblogs.com/zzrblog/p/4208905.html