Volley详解(一)——基本构架

前言

最近一个项目用到Volley处理网络请求,于是借这个机会研究下源码。Volley是2013 Google I/O上发布的网络请求框架,适合小而频繁的网络通信,源码发布在https://android.googlesource.com/platform/frameworks/volley,同时推荐GitHub上的一个非官方镜像项目https://github.com/mcxiaoke/android-volley


简介

作为一款优秀的框架,Volley具有很高的扩展性。其基本架构是面向接口编程的,这部分代码位于com.android.volley,同时也给出了默认的实现,这部分代码位于com.android.volley.toolbox,如果需要扩展,只需要自己实现com.android.volley.toolbox包中的类即可。


使用

作为铺垫,先hello world一下Volley的使用。

Step 1:

com.android.toolbox.volley类有4个重载的静态方法,用于构建RequestQueue

public static RequestQueue newRequestQueue(Context context);
public static RequestQueue newRequestQueue(Context context, HttpStack stack);
public static RequestQueue newRequestQueue(Context context, int maxDiskCacheBytes);
public static RequestQueue newRequestQueue(Context context, HttpStack stack, int maxDiskCacheBytes);

这4个重载的方法会调用RequestQueue的构造函数及其start()方法,使相关的Dispatch线程开始工作。

Step 2:

有了RequestQueue之后,我们只需要调用如下方法向请求队列中加入请求即可发起网络请求:

public <T> Request<T> RequestQueue.add(Request<T> request);

好了,这只是个简单的认识,接下来开始详细分析。


核心类

简单列出框架的核心类,大致被我分为以下4部分:

  • Request
    Request<T>:代表一个请求(抽象类)
    RequestQueue:存放各种状态下的Request,不要被名字迷惑,它不是一个简单的Queue,而是包含两个Queue,一个Set,一个Map

  • Response
    Response<T>:代表一个请求结果
    ResponseDelivery:处理Response(接口)
    ExecutorDelivery:这是ResponseDelivery的默认实现

  • Cache
    Cache:负责缓存的存取、更新等(接口)
    Cache$Entry:缓存中保存的内容(静态内部类)
    CacheDispatcher:缓存分发线程

  • Network
    Network:负责发起网络请求(接口)
    NetworkResponse:网络请求返回的结果
    NetworkDispatcher:网络请求分发线程


基本流程

有了核心类,就可以给出大致的工作流程了。

请求(Request)

Request<T>

它是个抽象类,保存了请求的类型,URL,参数,header,body,优先级,响应错误处理回调接口等,泛型参数<T>表示该请求返回的数据类型。Volley中给出了StringRequestJsonRequestImageRequest三种默认实现,我们也可以按需要给出自定义的实现。
Request<T>有两个重要的抽象方法,它们定义了请求完成后的处理方式:

abstract protected Response<T> parseNetworkResponse(NetworkResponse response);
abstract protected void deliverResponse(T response);

RequestQueue

RequestQueue维护了如下4个集合,表示了整个框架中各种状态下的Request

  • PriorityBlockingQueue<Request<?>> mCacheQueue
    缓存请求队列

  • PriorityBlockingQueue<Request<?>> mNetworkQueue
    网络请求队列

  • Set<Request<?>> mCurrentRequests
    正在执行中的网络请求,文档中用了“in flight”这个词,很贴切

  • Map<String, Queue<Request<?>>> mWaitingRequests
    等待请求的集合,如果一个请求正在被处理(即in flight)并且可以被缓存,则后续的具有相同url的请求,将进入此等待队列


响应(Response)

NetworkResponse

这是网络请求返回的原始结果,包括statusCodeheader,结果主体byte[] data等。

Response<T>

它保存了加工后的请求结果<T> result,对应的要放入缓存的内容Cache.Entry cacheEntry,错误VolleyError error。前面讲Request中提到的Request.parseNetworkResponse()方法会在工作线程中将原始的NetworkResponse转化为Response<T>,并交给ResponseDelivery处理。

ResponseDelivery

这是个接口,它只有三个方法,负责处理最终的结果(或错误):

public void postResponse(Request<?> request, Response<?> response);
public void postResponse(Request<?> request, Response<?> response, Runnable runnable);
public void postError(Request<?> request, VolleyError error);

ExecutorDelivery

这是Volley里给出的ResponseDelivery的默认实现,它的工作流程是这样的:

  • ExecutorDelivery的构造函数传入的参数中通过new Handler(Looper.getMainLooper())获取了主线程的Handler
  • postResponse()postError()方法会根据传入的RequestResponseRunnableVolleyError等参数,构造出一个新的Runnable对象,新的Runnable包含了主线程所要做的全部回调工作。
  • 调用Handler.post(Runnable runnable)将上一步构造出来的新的Runnable发送给主线程LooperMessageQueueVolley的任务也就完成了。

缓存(Cache)

Cache

这是表示缓存的接口,提供了get()put()remove()等基本操作,它包含一个静态内部类Cache$Entry,包括数据主体byte[] data,以及与过期策略有关的时间期限等内容,缓存与外界的读写操作都是以Entry为单位进行的。

DiskBasedCache

这是VolleyCache接口的默认实现。

  • 定义了DiskBasedCache$CacheHeader内部类,用于存储对应请求的header,用一个基于访问顺序accessOrder(而非插入顺序insertOrder)的LinkedHashMap<String, CacheHeader>存储这些header,而缓存的主体则是存放在File中,文件名通过CacheHeaderkey计算得到,keyFile一一对应。
  • 写缓存时,将Entry中的数据主体通过Stream写入File,将其他内容放入CacheHeader
  • 读缓存时,Entry的数据主体通过StreamFile中读入,其他内容从CacheHeader读入。

CacheDispatcher

  • 这是个线程,继承了Thread,每个RequestQueue对应一个CacheDispatcher,它的run()方法会不断从RequestQueue的缓存请求队列mCacheQueue<Request<?>>中取出Request进行处理。
  • 如果mCache中可以找到对应的缓存结果并且没有过期,则取出缓存,构造对应的Response,并将RequestResponse一起交给ResponseDelivery处理即可。
  • 如果mCache中找不到对应的缓存结果或者过期了,则将该Request加入到网络请求队列mNetworkQueue<Request<?>>中,等待发起网络请求。

网络(Network)

Network

这是网络请求接口,只有一个方法,用于发起请求:

public NetworkResponse performRequest(Request<?> request) throws VolleyError;

BasicNetwork

这是VolleyNetwork接口的默认实现。performRequest()方法中会调用HttpStack发起网络请求,具体代码略多,仍有待研究。

NetworkDispatcher

  • 这是个线程,继承了Thread,每个RequestQueue对应多个(默认4个)NetworkDispatcher,它的run()方法会不断从RequestQueue的网络请求队列mNetworkQueue<Request<?>>中取出Request进行处理。
  • 对于取出的每个Request,调用mNetwork发起网络请求,请求成功后,将得到的结果NetworkResponse转化为Response<T>,交给ResponseDelivery处理。
  • 如果该结果需要缓存,则调用mCache.put()写缓存。

总结

// TODO 此处应有流程图一张,懒得画了,改天再补。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值