Volley

本文深入介绍了Android网络框架Volley的特性与实现原理,包括数据缓存机制、错误重试策略、任务调度流程以及图片请求处理等方面的内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关于Android 网络框架
  1. 大数据上传和下载
    这里边的难点是数据太大,在处理上传下载的时候要有相应的数据完整安全机制,大部分应用是不会单独处理这样的问题的,要实现可参考Android系统的下载管理。
  2. 小数据上传和下载
    相反,网络的请求和小数据上传是现在几乎所有应用都必须涉及到,Volley, AsyncHttpClient等都是优秀的网络请求处理框架。

既然是框架,他们都处理了什么问题呢?

  1. 数据缓存
  2. 请求错误重试
  3. 网络异步请求封装
  4. 网络切换重连
  5. 简化上传数据的打包
  6. 提供请求的排序,取消等功能
  7. 请求连接池,减少单独的网络连接消耗的电量和流量

Volley提供异步的获取网络数据和阻塞的获取网络数据,阻塞的方法需在后台线程工作。

// GET方式
// 1.生成Request
// 2.加入请求队列中
// 3.等待callback
public void get() {
        String url = "www.baidu.com";
        Request request = new StringRequest(Request.Method.GET, url, new  Response.Listener<String>() {
            @Override
            public void onResponse(String response) {

            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {

            }
        });

        Volley.newRequestQueue(context).add(request);
 }

// 1.生成Request和创建RequestFuture
// 2.加入请求队列中
// 3.等待结果
public void blockGet() {
        String url = "www.baidu.com";
        RequestFuture<String> requestFuture = RequestFuture.newFuture();
        Request stringRequest = new StringRequest(Request.Method.GET, url, requestFuture, requestFuture);
        requestFuture.setRequest(stringRequest);
        Volley.newRequestQueue(context).add(stringRequest);

        try {
            String response = requestFuture.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
}

// Post
// 创建Request
// override getParams() 传递参数
// 加入队列等待结果
public void post() {
        String url = "www.baidu.com";
        Request request2 = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {

            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {

            }
        }){
            @Override
            protected Map<String, String> getParams() throws AuthFailureError {

                Map<String, String> postParams = new HashMap<>();
                postParams.put("xxx", "xxx");

                return postParams;
            }
        };

        Volley.newRequestQueue(context).add(request2);
}
Volley框架
 1. Cache                  缓存               (NoCache, DiskBasedCache)
 2. Network                网络响应解析        (BasicNetwork)
 3. HttpStack              网络请求处理        (HurlStack, HttpClientStack)
 4. Request                网络请求           (StringRequest, JsonRequest ...)
 5. ResponseDelivery       响应分发           (ExecutorDelivery)
 6. NetworkDispatcher      网络任务调度器
 7. CacheDispatcher        缓存任务调度器
 8. RetryPolicy            错误重试           (DefaultRetryPolicy)
Volley框架之缓存

所谓无缓存不应用,几乎所有网络应用都带Cache设计,Cache的设计已经到达了框架要作处理的级别,无论是从用户流量电量,还是公司服务器的压力考虑,缓存是必须的。

Cache 提供基本GET和PUT行为;
NoCache 不缓存;
DiskBasedCache 磁盘缓存默认实现,缓存算法是现在是几乎所有缓存框架都支持的LRU算法。 如果对默认的一级缓存不满足需求,可实现二级缓存,中间添加一层Memory Cache,优先使用内存缓存,在Fetch数据的时候,更有效率, 这属于内存空间换效率的做法,另外根据需求可以对缓存的算法自定义,比如FIFO,LIFO, Volley提供很方便的接入。
Cache.Entry 缓存数据结构
缓存策略,在HTTP协议下, 浏览器与服务器之间交互的时候为了不频繁的访问服务器,会在HTTP的请求头中做Cache-Control,但是由于浏览器没法对用户的磁盘进行读写,所以浏览器的缓存都是做在内存,Volley缓存也是同样的,不过Volley做了磁盘Cache。

缓存过程:

  1. 客户端请求一个URI指定的资源A。
  2. 服务器返回A,并在给A加上一个Last-Modified/ETag
  3. 客户端展现该资源,并将资源连同Last-Modified/ETag一起缓存本地,缓存的算法在DiskBasedCache 中。
  4. 客户再次请求资源A,并将上次请求时服务器返回的Last-Modified/ETag一起传递给服务器。
  5. 服务器检查该Last-Modified或ETag,并判断出该资源自上次客户端请求之后还未被修改(缓存是否过期),直接返回响应304和一个空的响应体,这时候Volley将Disk中Cache返回给前端调用。

Volley为了使缓存读写更加有效率, 定义了一个数据结构ByteArrayPool,避免不断的申请和释放Stream数据读写的消耗。

1) 什么是”Last-Modified”?
在浏览器第一次请求某一个URL时,服务器端的返回状态会是200,内容是你请求的资源,同时有一个Last-Modified的属性标记此文件在服务期端最后被修改的时间, 格式类似这样:
Last-Modified: Fri, 12 May 2006 18:53:33 GMT
客户端第二次请求此URL时,根据 HTTP 协议的规定,浏览器会向服务器传送 If-Modified-Since 报头,询问该时间之后文件是否有被修改过:
If-Modified-Since: Fri, 12 May 2006 18:53:33 GMT
如果服务器端的资源没有变化,则自动返回 HTTP 304 (Not Changed.)状态码,内容为空,这样就节省了传输数据量。当服务器端代码发生改变或者重启服务器时,则重新发出资源,返回和第一次请求时类似。从而保证不向客户端重复发出资源,也保证当服务器有变化时,客户端能够得到最新的资源。

2) 什么是”Etag”?
HTTP 协议规格说明定义ETag为“被请求变量的实体值“。 另一种说法是,ETag是一个可以与Web资源关联的记号(token)。典型的Web资源可以一个Web页,但也可能是JSON或XML文档。服务器单独负责判断记号是什么及其含义,并在HTTP响应头中将其传送到客户端, 以下是服务器端返回的格式:
ETag: “50b1c1d4f775c61:df3”
客户端的查询更新格式是这样的:
If-None-Match: W/”50b1c1d4f775c61:df3”
如果ETag没改变,则返回状态304然后不返回,这也和Last-Modified一样。

关于更多HTTP协议头字段和HTTP响应值代表的意义,篇幅有点大,会在新的文章中描述……

Volley任务调度
CacheDispatcher                   缓存任务调度处理,是一个一直运行着的Thread,不断的从队列中取任务和处理任务
NetworkDispatcher                 网络任务调度处理,是一个一直运行着的Thread,不断的从队列中取任务和处理任务,不过是说好的连接池,维护默认4个这样的线程在调度任务,并发处理
PriorityBlockingQueue             BlockingQueue实现者之一, 并发任务几乎都用到的一个数据结构,PriorityBlockingQueue 提供队列任务的自定义排序,在单独解释图片框架的时候,会详细讲到改数据结构可实现的算法。

任务调度过程:

  1. 添加一个 Request, 判断该Request是否已经被添加过了​,若是添加过,将其添加的一个统一的List A中等待,若是没添加到CacheQueue中,
  2. CacheDispatcher 处理CacheQueue中的请求,判断是否需要缓存,是否存在缓存,缓存是否过期,结果要么就是缓存,要么转移到NetworkQueue中,
  3. NetworkDispatcher 处理NetworkQueue中的请求,获得结果,做缓存,
  4. 遍历List A是否存在相同的请求在等待,若有,将所有同样的请求添加到CacheQueue中,
  5. 通过ResponseDelivery 将结果进行分发,成功的或者失败的结果,这个线程已经到Main中了。

注意:在整个调度的过程中,依赖的是Request中的getCacheKey()来做唯一性标识的,默认getCacheKey()的实现基于mUrl

public String getCacheKey() {
        return mMethod + ":" + mUrl;
}

对于GET方法的请求,该方法是有效的,因为GET方法mUrl是唯一指定的,若是POST方法请求,同类型的请求mUrl

都是一样的,这样会导致缓存混乱,所以,如果请求是POST,
override getCacheKey()来实现唯一的Key值。

// for POST
override
public String getCacheKey() {
    String params = "参数"; // getParams()
    return mMethod + ":" + mUrl + "/" + "params";
}
Volley错误重试机制

RetryPolicy, 设置访问出错的时,启用自动重试,在一些网络不稳定的环境下,有时候会发生网络重连,网络请求中断的情况,像这种场景下,我们希望,这些请求能够自动重试,而不是提示用户重试,Volley提供了可拓展的RetryPolicy介入自动重试SocketTimeoutException
ConnectTimeoutException自动重试,其中重试之前会提供接口,方便我们代码介入,比如埋点

 public void retry(VolleyError error) throws VolleyError;
Volley之Https支持

篇幅太大,关于网络安全请求,新文章阐述。

Volley中的图片请求和处理

Volley中单独提供了关于Bitmap的请求和处理,基于上述的任务调度,添加了对Bitmap的特殊处理,实际中像对Bitmap的框架更多(UIL Picasso Fresco …),相对Volley开发成本低很多,Bitmap的请求重点在于大量图片的处理、缓存过程不出现OOM,且快速Fetch到图片和节约流量。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值