美文网首页
网络请求之浅谈Volley的那些坑与改进(一)

网络请求之浅谈Volley的那些坑与改进(一)

作者: 2cf8219fe3a1 | 来源:发表于2016-11-10 14:45 被阅读0次

深入Volley之前,有必要回顾下几个知识点:

1.HTTP0.9 -> HTTP1.0 ->HTTP1.1 ->HTTP2协议[注:为什么不是2.0,协议制定委员会说以后只存在HTTPX];Google—HTTP协议;

2.HTTP2优点:相比较HTTP1.1主要两大改进:1.可复用TCP连接;2.所有报文信息都将是二进制传输,采用GZIP或COMPRESS压缩方式;有必要百度下这两点的实际原理;

3.目前为什么国内很多网站没有HTTP全站替换HTTPS,速度是主要原因:想想SSL和TLS的握手还要加上HTTP默认TCP三次握手,测试显示增加访问时间3倍左右;

说明:本文不会具体分析每个类的作用。[每个类都很优美,例如ByteArrayPool这个类]

目前为止除了OkHttp的框架,个人认为遇到的最优秀网络请求框架,本文仅从以下几点谈下Volley:

1,高度可扩展性(支持https )

2,重定向url问题

3,协议内容类型 传参问题

4,Cache缓存机制

5,对大多数客户端封装的Volley数据展示层向上层抛出数据修改意见

1.高度可扩展性(支持https )

if (stack == null) {          

  if (Build.VERSION.SDK_INT >= 9) {                

stack = new HurlStack();          

  } else {                

// Prior to Gingerbread, HttpUrlConnection was unreliable.              

  // See: http://android-developers.blogspot.com/2011/09/androids-http-clients.html                stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));          

  }        

}

volley提供了HttpStack抽象类,极大的扩展性,方便接入HttpURLConnection | OKHTTP等;在Android2.3之前,使用AndroidHttpClient是由于HttpURLConnection调用 close() 函数会影响连接池,导致连接复用失效,若使用需要关闭keepAlive,极大的不方便,每次HTTP请求都有。另外在HttpURLConnection 默认开启了 gzip 压缩,提高了 HTTPS 的性能,Android4.0 HttpURLConnection 支持了请求结果缓存。

2.重定向url问题

BasicNetwork.performRequest方法

 // Handle moved resourcesif (

statusCode == HttpStatus.SC_MOVED_PERMANENTLY || statusCode ==                  HttpStatus.SC_MOVED_TEMPORARILY) {            

    String newUrl = responseHeaders.get("Location");               

 request.setRedirectUrl(newUrl)

; }

这里可能会有问题,对于业务约定的只重定向GET请求且参数或Cookie不变的话没有问题,否则需要手动修改重定向参数;

3.协议内容类型 

传参问题Content-Type问题[参考http://www.alloyteam.com/2015/06/yong-volley-cai-di-keng/]

4,Cache缓存机制

[参考:http://www.a.codekk.com/detail/Android/grumoon/Volley%20源码解析]

Volley 构建了一套相对完整的符合 Http 语义的缓存机制。

优点和特点

(1). 根据Cache-Control和Expires首部来计算缓存的过期时间。如果两个首部都存在情况下,以Cache-Control为准。

(2). 利用If-None-Match和If-Modified-Since对过期缓存或者不新鲜缓存,进行请求再验证,并处理 304 响应,更新缓存。

(3). 默认的缓存实现,将缓存以文件的形式存储在 Disk,程序退出后不会丢失。缓存的再验证方面,在构建If-Modified-Since请求首部时,Volley 使用了服务端响应的Date首部,没有使用Last-Modified首部。整个框架没有使用Last-Modified首部。这与 Http 语义不符。private void addCacheHeaders(Mapheaders, Cache.Entry entry) {    // If there's no cache entry, we're done.    if (entry == null) {        return;    }    if (entry.etag != null) {        headers.put("If-None-Match", entry.etag);    }    if (entry.serverDate > 0) {        Date refTime = new Date(entry.serverDate);        headers.put("If-Modified-Since", DateUtils.formatDate(refTime));    }}服务端根据请求时通过If-Modified-Since首部传过来的时间,判断资源文件是否在If-Modified-Since时间 以后 有改动,如果有改动,返回新的请求结果。如果没有改动,返回 304 not modified。Last-Modified代表了资源文件的最后修改时间。通常使用这个首部构建If-Modified-Since的时间。Date代表了响应产生的时间,正常情况下Date时间在Last-Modified时间之后。也就是Date>=Last-Modified。通过以上原理,既然Date>=Last-Modified。那么我利用Date构建,也是完全正确的。可能的问题出在服务端的 Http 实现上,如果服务端完全遵守 Http 语义,采用时间比较的方式来验证If-Modified-Since,判断服务器资源文件修改时间是不是在If-Modified-Since之后。那么使用Date完全正确。可是有的服务端实现不是比较时间,而是直接的判断服务器资源文件修改时间,是否和If-Modified-Since所传时间相等。这样使用Date就不能实现正确的再验证,因为Date的时间总不会和服务器资源文件修改时间相等。尽管使用Date可能出现的不正确情况,归结于服务端没有正确的实现 Http 语义。但我还是希望 Volley 也能完全正确的实现 Http 语义,至少同时处理Last-Modified和Date,并且优先使用Last-Modified。

5,对大多数客户端封装的Volley数据展示层向上层抛出数据修改意见

目前响应靠new Thread向上抛数据会极大地可能造成线程竞争或死锁,同样也会内存抖动问题;/** 响应监听  **/    private ListenerresponseListener = new Listener() {        @Override        public void onResponse(final T response) {            if (mCanceled) {                // 如果取消了,直接返回                return;            }            new Thread(new Runnable() {                @Override                public void run() {                    Message message = mHandler.obtainMessage();                    message.obj = onNetResponse(response);                    mHandler.sendMessage(message);                }            }).start();        }    };建议实现线程池来处理,参考Volley的ExecutorDelivery类设计思想private ExecutorPostResult mExecutorPostResult = new ExecutorPostResult(new Handler(Looper.getMainLooper()));/** 响应监听  **/    private ListenerresponseListener = new Listener() {

@Override

public void onResponse(final T response) {

if (mCanceled) {

// 如果取消了,直接返回

return;

}

// 由于解析需要时间,启动子线程

mExecutorPostResult.postResponseResult(SuningNetTask.this,onNetResponse(response));

}

};

相关文章

网友评论

      本文标题:网络请求之浅谈Volley的那些坑与改进(一)

      本文链接:https://www.haomeiwen.com/subject/bpkxpttx.html