Volley与Picasso的对比

想写一篇文章来对比一下Volley以及Picasso,有人或许会说了,Volley和Picasso的服务对象都不同,Picasso是专注于图片的下载以及处理,而Volley则适应于任何轻量的网络请求。是的,的确如此,那我们不如就图片下载缓存这个应用场景展开来,来对比分析Volley和Picasso的相同之处与不同之处。

首先我们先来看一下Volley和Picasso的整体框图。

Volley:

 

volley-arch

 

Picasso: 

Picasso-整体架构

 

其中Volley是官方给出的整体框架图,而Picasso是我自己根据源代码抽离出来的,可能有些地方不是那么准确,请大家指教。先说一下从上面两张框架图对比,发现的其中的不同之处:

  • 对请求对象的封装不同:
    • 在Volley中,请求会直接封装在Reqeust当中,包括目标的网址/回调的接口等等信息,直接提交给CacheDispatcher即可。
    • 在Picasso中,一个请求会依次封装成ReqeustCreator,Reqeust,Action等不同状态,其中ReqeustCreator是用于创建Reqeust,在ReqeustCreator中可以设置图片的地址,大小,是否居中,是否旋转,图片的后处理等等参数,通过ReqeustCreator中拥有一个RequestBuilder对象;当用户调用into(Target)方法的时候,通过RequestBuilder中的build()方法,会构造出Reqeust,然后构造出对应的Action方法,提交至Dispatcher队列进行处理。
  • Dispatcher不同:
    • 在Volley中,Dispatcher包括CacheDispatcher和NetworkDispatcher两部分,其中CacheDispatcher只有一个线程,而NetworkDispatcher默认会有4个线程在执行。
    • 在Picasso当中,所有的任务的分发都是通过一个Dispatcher,即DispatcherThread工作线程来完成。
  • 消息的传递方式不同:
    • 当添加任务的时候:
      • Volley是通过阻塞队列实现,所有的Dispatcher(包括CacheDispatcher和NetworkDispatcher)。
      • Picasso添加任务是通过Handler,将Action作为消息的Message中的object的进行传递。
    • 当任务结束,发送消息的时候:
      • Volley是通过Handler实现,但不会在消息中传递具体的任务,而是负责发送消息,并使用handler.post()方法将要执行的代码发送到主线程上执行。
      • Picasso是将任务的包装类BitmapHunter作为Message的object来进行传递。
  • Cache
    • MemoryCache
      • Volley中,对于普通的任务,并没有设定MemoryCache,我理解的这是因为Volley的设计初衷是用于那些轻量级的网络访问,一般不会占用太大内存,所有不需要再使用MemoryCache,使用DiskBasedCache,性能也能满足。而服务于图片的ImageLoader,其中明确要求我们实现一个MemoryCache以供使用。
      • Picasso由于其设计服务对象就是图片,因此其本身自带的Cache就是MemoryCache
    • DiskCache
      • Volley中默认实现的Cache就是DiskBasedCache,根据网络请求结果根据情况保存在Cache当中。
      • Picasso其本身并不支持DiskCache,但根据我在StackOverflow查到的结果,有网友说,其DiskCache依赖于其网络库,默认的为Square自己的OKHttp,okhttp内部已经实现有网络Cache,未考察(参考:stackoverflow)。
  • 支持的请求来源不同:
    • Volley仅支持从网络上访问图片或者其他的资源。
    • Picasso支持从网络,File,Resource,Asserts中加载图片。
  • 支持的请求对象不同:
    • Volley支持图片,Json,String等等各种各样的网络请求,而且可以很容易的扩展自己的实现。
    • Picasso仅仅支持图片。
  • 任务优先级的支持:
    • Volley支持任务的优先级
    • Picasso没有任务的优先级这一说
  • 图片后续处理的支持:
  • 任务的暂停
    • Volley不支持
    • Picasso支持,通过调用Picasso中的pauseTag(Object tag)实现

 

说完不同的,再来看看Volley和Picasso在设计的时候都考虑到的地方,这也是在我们需要设计自己的图形缓存库的时候,更加需要注意到的地方:

  • 主线程仅负责任务的添加和完成时的回调,其他的任务又其他线程负责处理
    • 老生常谈了,主线程不能做太多的事情,否则ANR有好看的。
  • 允许多个任务同时进行处理
    • 多个线程是优化效率的一种特别有效的手段,比如多个任务同时进行的时候,可以同时下载,提高效率。
  •  根据不同的网络情况,按需调整或者重新设置同时工作线程数目:
    • Volley和Picasso当中,都根据网络状态的不同,规定了不同的同时进行的网络请求数目,既能充分利用网络,又不至于榨干系统网络请求资源。 这个地方是我之前理解有错误,在默认情况下,Picasso是可以根据网络的不同设置不同的网络请求并发数目,但实际上Volley中并不存在这个功能,其默认newRequestQueue生成的ReqeustQueue其指定的并发数目为4,因此如果有需要,需要自己手动编写一层封装,以实现根据网络状态设置工作线程数目的目的。感谢千醉z
  • 要有Cache
    • 分为MemoryCache和DiskCache,MemoryCache不多说了,对于图片来说,必须要有的,要不频繁解码,容易OOM不说,解码消耗的大量时间,用户体验也会很差。
  • 支持批量任务的添加、删除、暂定
    • 比如当一个Activity退出的时候,总要有办法能够同时取消该Activity对应的所有的网络请求的。
  • 避免OOM
    • 同一个时刻,仅仅允许一张图片进行解码操作,这个Picasso是从Volley中学来的。

 

大体上就想到这些,总体上,如果我们的需求仅仅需要处理图片,那么Picasso在功能上可以说远远要优于Volley,是我们的第一选择,但如果我们图片的需求并不是特别强烈,同时还在网络上传输一些数据,那么Volley可能更加适合。如果大家有别的看法,一起讨论。

 

 

 

 

原创文章,转载请注明: 转载自闭门造车

本文链接地址: Volley与Picasso的对比

  1. 任务优先级的支持:
    Volley支持任务的优先级
    Picasso没有任务的优先级这一说

    这点不太准确,Picasso的话对Bitmaphunter是有优先级之分的,毕竟PicassoExecutorService实际处理的是Bitmaphunter,在submit的时候的会把BitmapHunter包装成PicassoFutureTask,然后PicassoFutureTask内部是实现了Comparable接口的。

    • 哈哈,你读的代码应该比我仔细多了,这个是好久之前看的,也都忘了差不多了。你们现在还用这个图形库吗?其实也可以关注下Fresco、Glide。

  2. 避免OOM
    同一个时刻,仅仅允许一张图片进行解码操作,这个Picasso是从Volley中学来的。

    楼主,这个不太准确吧,volley在解码的时候确实是加锁的,但是Picasso是在transformResult中进行加锁的,decodeStream的时候并未加锁。

  3. 您好,他的磁盘缓存怎么做的,有那个urlconnection.setCache(true),不懂啊求指教

  4. Volley和Picasso当中,都根据网络状态的不同,规定了不同的同时进行的网络请求数目,既能充分利用网络,又不至于榨干系统网络请求资源。请问一下,这个在Volley中是在哪里设置的? 没看到啊。

    • Hi,抱歉,这个地方应该是我记错了,Volley中默认并不会根据网络的状态自动设置最大并发数目,但可以手动指定。当我们使用Volley.newRequestQueue(Context context)构建默认初始化的Volley请求队列的时候,是默认使用4个并发线程的。如果需要这个功能,可以自己写一层封装就可以,已经在原文中修正,谢谢!