Volley源代码学习总结

Volley整体框架设计

volley-arch

 

其实Volley的整体框架就是如上所示,在主线程当中,会维护一个ReqeustQueue,我们要添加的任务,都会添加到这个Reqeust队列当中;任务添加进来之后,运行于cache线程的CacheDispatcher就会取走Reqeust,然后要不从cache中获取结果,要不然发送给NetworkDispatcher;再然后就是NetworkDispatcher从其对应的队列取Request,执行操作。

我们以ImageLoader的典型用法,来分析一下其具体的工作流程:

final ImageView imageView = (ImageView)findViewById(R.id.imageview);
RequestQueue queue = Volley.newRequestQueue(getApplicationContext());
ImageLoader imageLoader = new ImageLoader(queue, new LruBitmapCache(getApplicationContext()));
imageLoader.get("http://www.baidu.com/img/bdlogo.png", ImageLoader.getImageListener(imageView, R.drawable.ic_launcher, R.drawable.ic_launcher));
  1.  ImageLoader根据传入的Image Url和ImageListener,构建一个ImageContainer以及对应的Reqeust<Image>
    1. 尝试从MemoryCache中获取对应的图像,如果成功,则直接调用ImageListener回调方法
    2. 构建ImageContainer,并通过ImageListener通知需要设置默认的图片
    3. 根据当前正在执行的任务,查看是否有可以Batch在一起的请求,打包成为BatchImageRequest,其中包含组合在一起的Reqeust的各种信息
    4. 构建需要提交给Volley的Reqeust<Image>。
  2. ImageLoader将步骤1中构建的Reqeust<Image>提交到ReqeustQueue。
  3. ReqeustQueue:该Reqeust是否需要DiskCache?
    1. 不需要:则直接将Request添加至mNetworkQueue当中。
    2. 需要:首先检查当前的需要DiskCache的任务当中是否有正在执行的与之Cache Key匹配的任务?
      1. 存在:添加Request到对应的队列当中,等待结果。
      2. 不存在:将Request添加到mCacheQueue当中。
  4. CacheDispatcher从队列mCacheQueue中获取优先级最高的任务
    1. 检查该任务在DiskCache中是否已经存在?
      1. 不存在:将Request添加到mNetworkQueue当中。 
      2. 存在:检查是否超过有效期
        1. 超过:将Request添加到mNetworkQueue队列当中。
        2. 没有超过:Cache Hit,检查是否需要后台刷新数据?:
          1. 不需要:通过ResponseDelivery(本质上Handler),发送Cache Hit结果
          2. 需要:ResponseDelivery(本质上Handler),发送Cache Hit结果,之后再将任务提交至mNetworkQueue
  5. NetworkDispatcher从队列mNetworkQueue当中获取优先级最高的任务
    1. 执行网络访问请求
    2. 判断该Reqeust是否需要Cache,若需要,则写入Cache
    3. mDelivery.postResponse(request, response);通知主线程处理结果。
  6. ResponseDelivery中的Handler接收处理结果消息,回调处理具体任务。

这样一看,整体的流程就很清晰了。这里举例使用的是Imageloader,如果是其他的Reqeust,则是省略步骤1即可。

那Response回调是怎么保证在UI线程上执行的呢?

在ReqeustQueue的构造函数中,可以配置DeliverDispatcher,而这个Dispatcher中有一个Handler,该Handler的Looper是主线程的Looper,也就是所有发送到对应的Handler的事件都会在主线程当中得到处理。这样也就是保证了Response回调都是在主线程上进行的。也就是可以直接在回调函数中设置UI控件的属性。

Volley适用的场景

想起来Google IO大会上介绍Volley的PPT中,有这样一张图:

volley-use-scene

看到这张图就想起来,适用于同时发生的大量的一次性请求。

Volley不适用的场景,为什么不适用?

知道了Volley应该的用处,当然其他的就是不适应的,比如说,下载一个文件?为什么不适应,那下载文件来说,其最大的特点就是,响应稍微慢点也可以,多个任务甚者可以一个一个的来;支持断点续传这是应该必须的吧;Volley接收到的数据都是保存在一个数组当中供后续解析,什么?你要下载个文件,总不能都写到数组里面去吧;Volley没有为这些做优化。

Volley对于OOM问题的处理

OOM的问题,Volley处理的还是蛮细致的,当然也没有太消耗体力:

  • 同一个时刻只解析一张图片
  • 构建了一个简单的Byte的Pool避免Heap猛增。
  • 。。。其他的还没想到

等Picasso分析完了再对比一下。

About: happyhls


发表评论

电子邮件地址不会被公开。 必填项已用*标注