Android网络库比较:OkHTTP、Retrofit和Volley

597

一个iOS开发者正在学习Android,正在开发一个Android项目,该项目将会从JSON到图像再到音视频流进行各种请求:

  1. 在iOS上,我经常使用AFNetworking项目。Android是否有相应的库?

  2. 我已经研究了Square的OkHTTPRetrofit以及Volley,但还没有通过它们进行开发的经验。我希望有人能提供每个库的最佳用例的实际示例。从我所读到的来看,OkHTTP似乎是这三个库中最强大的,并且可以处理此项目的要求(如上所述)。


3
如果您正在使用HttpUrlConnection的内部实现,您应该考虑到HttpUrlConnection在POST请求时使用了静默重试。这给我带来了很多损失。如需更多信息,请参阅此处:https://dev59.com/NF4d5IYBdhLWcg3wLf4g#37675253 - oli
1
如果有人需要所有网络库的列表,可以在我的博客文章中找到 https://androidredman.wordpress.com/2017/06/26/list-of-all-networking-libraries-in-android/ - Manohar
Volley 可以在遗留的 Apache、HttpUrlConnection、Apache-4 或 OkHttp 平台上运行。而 Retrofit 确实只能运行在 OkHttp 上。 相比之下,Retrofit 更容易配置。 - bitsabhi
10个回答

665
我希望有人能提供每个库最佳应用案例的具体示例。
如果你需要与 Web 服务通信,请使用 Retrofit。如果你需要下载图片,请使用同级库 Picasso。如果你需要进行超出 Retrofit / Picasso 范围的 HTTP 操作,请使用 OkHTTP。
Volley 大致上与 Retrofit + Picasso 竞争。优点是它只是一个库。缺点是它是一个不受支持的“把代码丢过去,然后做 I | O 演示”的库,文档缺失。
编辑-现在 Google 正式支持 Volley。请参阅 Google Developer Guide 根据我所读的,似乎 OkHTTP 是这三种库中最强大的。
如果可用,Retrofit 会自动使用 OkHTTP。Jake Wharton 提供了一个Gist将 Volley 连接到 OkHTTP。
并且可以处理此项目的要求(如上所述)。
也许您不会使用它们中的任何一个来进行“音频和视频的流式下载”,按照“流式传输”的传统定义。相反,Android的媒体框架将为您处理这些HTTP请求。
话虽如此,如果您要尝试自己进行基于HTTP的流式传输,则OkHTTP应该可以处理该场景;我不记得Volley能很好地处理该场景。Retrofit和Picasso都不是为此而设计的。

4
感谢 @CommonsWare 的简明回答,以及对Volley未记录的技巧的注释(与其他项目相比,这给人留下了这种印象)。这绝对有助于我启动项目。 - Alfie Hanssen
18
@CommonsWare的回答很好。有人可以跟进一下RoboSpice如何适用于这一切吗? - user1923613
3
如果您使用Volley进行网络调用,则无需使用Robospice! Volley可以完成Robospice在网络调用方面的许多功能。Robospice支持REST(使用Spring Android或Google Http Client或Retrofit)。如果您希望快速进行网络调用和图像加载,并且需要强大的网络客户端,则可以选择Volley。但是,您可以将普通的Android异步任务替换为Robospice,以获得更好的性能并避免内存泄漏。 - LOG_TAG
4
@frostymarvelous: 我认为没有文档和支持已经足够证明了。这并不意味着 Google 缺乏更正式处理此类事情的系统(例如 Android 支持库)。在回答发布两年后,好的一面是有一些社区支持,包括将代码非官方打包成一个工件。 - CommonsWare
4
您在评论两年前的答案。当时还没有文档记录。 - CommonsWare
显示剩余24条评论

368

在 Volley 的视角下,以下是一些与您需求相关的优势:

Volley 一方面完全专注于处理单个、小型 HTTP 请求。因此,如果您的 HTTP 请求处理存在某些怪癖,Volley 可能会为您提供钩子。另一方面,如果您的图像处理存在怪癖,您唯一真正的钩子就是 ImageCache。"这不是什么,但也不算太多!" 但它还有其他更多的优点,例如一旦定义了请求,从片段或活动中使用它们非常轻松,不像并行 AsyncTasks。

Volley 的优缺点:

Volley 有哪些好处呢?

  • 网络部分不仅限于图片。Volley旨在成为后端的重要组成部分。对于基于简单REST服务的新项目,这可能是一个巨大的优势。

  • NetworkImageView比Picasso更积极地清理请求,并且在其GC使用模式方面更加保守。NetworkImageView仅依赖于强内存引用,并在为ImageView发出新请求或该ImageView移出屏幕时清除所有请求数据。

  • 性能。本文不会评估这一点,但他们显然已经小心谨慎地处理了内存使用模式。Volley还努力批量回调到主线程以减少上下文切换。

  • Volley似乎也有futures。如果您感兴趣,请查看RequestFuture。

  • 如果您正在处理高分辨率压缩图像,则Volley是唯一有效的解决方案。

  • Volley可以与Okhttp一起使用(新版本的Okhttp支持NIO以获得更好的性能)

  • Volley与Activity生命周期兼容。

使用Volley时存在的问题:
由于Volley是新技术,目前还不支持某些功能,但已经得到修复。

  1. 多部分请求(解决方案:https://github.com/vinaysshenoy/enhanced-volley

  2. 状态码201被视为错误,现在200到207的状态码是成功响应。(已修复:https://github.com/Vinayrraj/CustomVolley

    更新:在Google volley的最新版本中,2XX状态码的bug已经修复了!感谢Ficus Kirkpatrick!

  3. 虽然文档较少,但许多人在Github上支持volley,可以找到类似Java的文档here。在Android开发者网站上,您可以找到使用Volley传输网络数据的指南Transmitting Network Data Using Volley。Volley源代码可在Google Git找到。

  4. 要解决/更改Volley框架的重定向策略,请使用Volley with OkHTTP(如上所述的CommonsWare)

此外,您还可以阅读这篇文章比较Volley和Picasso的图像加载

Retrofit:

它是由Square发布的,提供非常易于使用的REST API(更新:使用NIO支持)

Retrofit的优点:

  • 与Volley相比,Retrofit的REST API代码简洁,提供了优秀的API文档,并在社区中得到良好的支持!将其添加到项目中非常容易。

  • 我们可以使用任何序列化库和错误处理。

更新:

  • Retrofit 2.0.0-beta2带来了很多非常好的改变。

  • 使用OkHttp 2.0版本的Retrofit 1.6现在依赖于Okio,以支持java.iojava.nio,这使得使用ByteStringBuffer访问、存储和处理数据变得更加容易,可以进行一些聪明的优化,以节省CPU和内存。 (顺便说一下:这让我想起了Koush's OIN库,它支持NIO!)

  • 我们可以使用Retrofit和RxJava结合使用,使用rxObservables组合和链接REST调用,避免丑陋的回调链,从而避免回调地狱!

Retrofit 1.6的缺点:

  • 旧版本的Retrofit/OkHttp在处理内存相关的错误时功能不够完善,但不确定使用支持Java NIO的Okio是否有所改进。

  • 如果我们使用不当,最少的线程辅助可能会导致回调地狱。

(所有上述缺点都已在新版本的Retrofit 2.0 beta中解决)

========================================================================

更新:

Android Async vs Volley vs Retrofit 性能基准测试(毫秒,数值越小越好):

一个讨论 仪表板(7个请求) 25个讨论
AsyncTask 941 毫秒 4,539 毫秒 13,957 毫秒
Volley 560 毫秒 2,202 毫秒 4,275 毫秒
Retrofit 312 毫秒 889 毫秒 1,059 毫秒
< p > < em > (FYI Retrofit基准测试信息将随着Java NIO支持的提升而改善,因为新版本的OKhttp依赖于NIO Okio库)

在三次测试中,重复次数不同(1-25次),Volley的速度比AsyncTasks快50%至75%。Retrofit比AsyncTasks更快,速度惊人,快50%至90%,在相同的端点上访问相同的次数。在Dashboard测试套件中,这意味着加载/解析数据要快几秒钟。这是一个巨大的现实世界的差异。为了使测试公平,AsyncTasks / Volley的时间包括JSON解析,因为Retrofit会自动执行它。RetroFit在基准测试中获胜!最终,我们决定在我们的应用程序中使用Retrofit。它不仅速度极快,而且与我们现有的架构非常匹配。我们能够创建一个父回调接口,该接口自动执行错误处理、缓存和分页,而无需为我们的API做出太多努力。为了合并Retrofit,我们必须重命名变量,使我们的模型符合GSON规范,编写一些简单的接口,从旧API中删除函数,并修改我们的片段以不使用AsyncTasks。现在,我们已经完全转换了一些片段,这非常容易。虽然一开始遇到了一些技术问题/错误,但Square有一个非常棒的Google+社区,能够帮助我们解决这些问题。

何时使用Volley?!

当我们需要加载图像以及消耗REST API时,我们可以使用Volley!对于许多网络请求同时进行的情况,需要网络调用排队系统!此外,Volley比Retrofit具有更好的内存相关错误处理!

OkHttp可以与Volley一起使用,默认情况下,Retrofit使用OkHttp!它支持SPDY,连接池,磁盘缓存,透明压缩!最近,它还使用Okio库获得了一些Java NIO支持。

来源,来源:volley-vs-retrofit by Mr. Josh Ruesch

注意:关于流媒体,这取决于您想要的流媒体类型,例如RTSP / RTCP。


@Jan1337z 感谢提供这个信息!我已经更新了它!https://android.googlesource.com/platform/frameworks/volley/ - LOG_TAG
4
@LOG_TAG 在你的示例中对 RoboSpice 进行基准测试将是有趣的。我们甚至提供了一个 Retrofit 模块,所以我相信这只需要很少的更改。源代码在哪里可以找到? RS 的优点在于它能正确地处理执行网络请求的活动的生命周期,而且我们还提供透明缓存,我想相比于纯 Retrofit 请求,开销会很小。 - Snicolas
与AndroidQuery网络效率相比,您认为如何? - Rubin Basha
3
嗨!关于使用Volley进行多部分请求,我认为我们可以在其中使用httpmime库中的MultipartEntityBuilder - BNK
2
有其他人验证过这些基准吗?由于Apache Http库在M版本中已被弃用(而我正在使用它进行多部分构建器),因此我决定将我的网络代码迁移到Retrofit。我最初更改了其中一个GET调用以从服务器获取一堆对象。我计时了Retrofit与AsyncTask(使用自己的JSON解析)。性能非常接近,而不是表格中“One Discussion”列中显示的3倍改进。当然,生成的代码要干净得多,我不必编写自己的JSON解析器,但对于单个GET请求,改进并不存在。 - Gary Kipnis
显示剩余8条评论

43

RoboSpice与Volley

来自https://groups.google.com/forum/#!topic/robospice/QwVCfY_glOQ

  • RoboSpice(RS)基于服务,比Volley更符合Android的哲学。Volley基于线程,这不是在Android上进行后台处理的正确方式。虽然从根本上讲,这两个库都很相似,但我们处理后台进程的方式更加Android化,它允许我们告诉用户RS实际上正在后台执行某些操作,而这对于Volley来说会很困难(实际上根本不行)。
  • RoboSpice和Volley都提供了优秀的功能,如优先级设置、重试策略、请求取消等。但RS提供的更多:更高级的缓存机制,这是一个重大优势,具有缓存管理、请求聚合、重新连接到挂起的请求、处理缓存过期而不依赖服务器标头等更多功能。
  • RoboSpice会将更多操作放到UI线程之外:Volley会在主线程上反序列化POJO对象,这对我来说很糟糕。使用RS可以使您的应用程序更具响应性。
  • 在速度方面,我们确实需要有一些指标。现在RS已经变得非常快了,但仍然没有数据可以在此处放置。理论上Volley应该会更快一些,但现在RS已经实现了大量的并行操作......谁知道呢?
  • RoboSpice具有广泛的兼容性范围,并提供扩展功能。您可以将其与okhttp、retrofit、ormlite(beta)、jackson、jackson2、gson、xml序列化器、google http客户端、spring android等许多工具一起使用。Volley可以与okhttp一起使用,并使用gson。这就是全部了。
  • Volley提供了更多的UI界面:NetworkImageView,而RS则提供了spicelist适配器。在功能上没有太大差别,但我认为Volley在此方面更加先进。
  • RoboSpice自首次发布以来已解决了200多个错误。它非常稳定且在生产中被广泛使用。Volley的成熟度较低,但其用户基数应该在迅速增长(Google的影响)。
  • RoboSpice可以在maven central上找到。很难找到Volley ;)

  • Robospice使用Android服务进行REST调用,我们可以结合Retrofit使用Robospice来最小化gson解析的工作量,同样的方式,我们可以使用Volley(基于线程)与Robospice一起使用吗?(不确定这是否是正确的问题)我只是在寻找带有服务的Volley! - LOG_TAG
    1
    使用服务的Volley基本上就是RS。或者按时间顺序来说,Volley是没有服务和其他一些缺失功能的RS。是的,您可以在RS中使用Retrofit,甚至可以添加okhttp。 - Snicolas
    7
    为什么很难找到Volley库呢?compile 'com.mcxiaoke.volley:library:1.0.+' - Rob
    1
    @Rob,曾经有一段时间mcxiaoke的克隆版本不可用。你必须手动将Volley包含在你的应用程序中。 - frostymarvelous
    volley会在主线程中反序列化您的POJO对象。如果有问题,您可以在单独的线程上接收返回的JSON数据并进行反序列化处理。 - Johann
    如果你想要速度,使用Retrofit和RS的组合。对于其他任何事情(偏爱、易用性、文档、懒惰...哈哈),可以使用任何东西。 - Tamtomo Abdi Negoro

    20

    AFNetworking适用于Android:

    快速Android网络这里

    快速Android网络库支持所有类型的HTTP/HTTPS请求,如GET、POST、DELETE、HEAD、PUT和PATCH。

    快速Android网络库支持下载任何类型的文件。

    快速Android网络库支持上传任何类型的文件(支持多部分上传)。

    快速Android网络库支持取消请求。

    快速Android网络库支持为任何请求设置优先级(低、中、高、立即)。

    快速Android网络库支持RxJava。

    由于它使用OkHttp作为网络层,因此支持:

    快速Android网络库支持HTTP/2,允许所有针对同一主机的请求共享套接字。

    快速Android网络库使用连接池,可降低请求延迟(如果HTTP/2不可用)。

    透明GZIP可缩小下载大小。

    快速Android网络库支持响应缓存,避免完全重复请求的网络。

    感谢:该库是我创建的


    1
    你表示你的库支持HTTP/2,但你没有说明是否需要API支持HTTP/2。我的理解是,Android API级别低于5.0没有正确的SSL加密方法来支持HTTP/2。我不是在挑毛病,只是想全面评估你提出的解决方案。 - DoctorD
    @AmitShekhar:我只是想知道在Android中哪个API调用最好。我正在使用Android Networking Library,那么实现Retrofit、Volley还是Android Networking更好呢? - Parth Bhayani
    @Amit Shekhar,Fast Android Networking在多部分图像上传方面的效率如何?特别是在低网络情况下? - user3135923
    我在谷歌上搜索2022年HTTP客户端库比较时发现了这篇文章,但尽管Fast Android Networking Library仍然似乎是明显的赢家,但它已经有几年没有维护和更新了。不过,我找到了一个名为KnHttp的库,它是Fast Android Networking Library的直接分支,正在得到更新和维护。 - Nick Betcher

    18

    异步HTTP客户端loopj与Volley的比较

    我的项目需要每1-5分钟发送小型HTTP REST请求。

    我长期使用了一个异步HTTP客户端(版本为1.4.1)。相比使用原始的Apache httpClient或HTTP URL连接,它的性能更好。然而,新版本的库对我来说无法工作:库内部异常中断了回调链。

    阅读了所有答案后,我被激发尝试一些新的东西。我选择了Volley HTTP库。

    在使用一段时间后,即使没有测试,我清楚地看到响应时间已经降低到了Volley的1.5倍到2倍。

    也许Retrofit比异步HTTP客户端更好?我需要试试。但我确定Volley不适合我。


    有关Retrofit和AsyncHttpClient的任何分析吗?如果有,请在@Sergey处发布。 - IshRoid
    1
    http://instructure.github.io/blog/2013/12/09/volley-vs-retrofit/ - surya
    我已经使用AsyncHttpClient几年了。不好的一点是,github仓库已经两年没有提交了。 - Vitor Hugo Schwaab
    它已经不再是实际的了,异步HTTP也太老套了。考虑更换另一个库。Volley也成为了非常好的选择。 - Sergey Vakulenko
    Sergey,@IshRoid,我仍在等待您的回答。我正在使用AsyncHttpClient,是否应该使用其他东西如RxJava Retrofit等。请告诉我。迫不及待地等待着您的回复。 - Deep Dave
    @DeepDave 嘿,不要想太多,Retrofit是目前最好的库,直到Kotlin引入协程。 - IshRoid

    11

    根据我使用Volley的经验,补充一些讨论:

    1. Volley不处理流式上传或下载。也就是说,整个请求体必须在内存中,并且不能使用OutputStream将请求体写入底层套接字,也不能使用InputStream读取响应体,就像基本的HttpURLConnection一样。因此,如果要上传或下载大文件,Volley是一个糟糕的选择。您的请求和响应应该很小。这是我个人遇到的最大限制之一。值得一提的是,OkHttp确实有用于处理流的接口。

    2. 缺乏官方文档令人恼火,尽管我通过阅读源代码来解决了这个问题,源代码非常易于理解。更让人烦恼的是,据我所知,Volley没有官方发布版本,也没有Maven或Gradle工件,因此管理它作为依赖关系比例如Square发布的任何库都更麻烦。您只需克隆一个repo,构建一个jar,然后自己解决。寻找错误修复程序?获取并希望它在那里。您可能还会得到其他一些内容;它将不会被记录。我认为,这实际上意味着Volley是一个不受支持的第三方库,尽管代码库相当活跃。买家自负。

    3. 作为一个小问题,将Content-Type绑定到类/请求类型(JsonObjectRequest、ImageRequest等)有点笨拙,并且会使调用代码的灵活性减少一些,因为您被绑定到Volley现有的请求类型层次结构中。我喜欢直接设置Content-Type作为任何其他标头的简单性(顺便说一句,不要在Volley中这样做;否则,您将得到两个Content-Type标头!)。虽然这只是我的个人意见,但可以解决这个问题。

    这并不意味着Volley没有一些有用的特性。它当然有。容易定制的重试策略,透明缓存,取消API和支持请求调度和并发连接都是很棒的功能。只需要知道它不适用于所有HTTP使用案例(见上文第1条),而且将Volley投入应用程序的生产使用中会涉及到一些麻烦(第2条)。


    完整的内存加载是在慢慢地折磨我。谢天谢地,有人也提到了这个问题。 - TheSunny
    该库还可以对您的请求正文进行防御性复制,因此对于大型请求,内存消耗可能是您预期的两倍。 - Jeff

    9

    我最近发现了一个名为ion的库,它为项目带来了额外的功能。

    ion内置了对图像下载的支持,并与ImageView集成,同时还支持JSON(借助GSON),文件和非常方便的UI线程处理。

    我正在一个新项目中使用它,到目前为止结果很不错。相比Volley或Retrofit,它的使用要简单得多。


    2
    Ion和Retrofit,你会推荐哪一个? - Sreekanth Karumanaghat
    Retrofit比ion更好。 - Rajesh Koshti

    4

    补充已接受的答案和LOG_TAG所说的...为了让Volley在后台线程中解析数据,您必须将Request<YourClassName>作为子类来进行子类化,因为onResponse方法在主线程上被调用,在主线程上解析可能会导致UI延迟,特别是当响应很大时。请在这里阅读如何实现。


    1
    正确的做法是在主线程之外解析Volley响应,这样当响应非常大时就不会导致UI卡顿。 - Gopal Singh Sirvi

    3

    Retrofit 1.9.0 vs. RoboSpice

    我在我的应用程序中同时使用这两个库。

    每当我解析嵌套的JSON类时,Robospice比Retrofit更快。因为Spice Manager会为您完成所有工作。在Retrofit中,您需要创建GsonConverter并进行反序列化。

    我在同一活动中创建了两个片段,并同时调用了两个相同类型的URL。

    09-23 20:12:32.830  16002-16002/com.urbanpro.seeker E/RETROFIT﹕   RestAdapter Init
    09-23 20:12:32.833  16002-16002/com.urbanpro.seeker E/RETROFIT﹕ calling the method
    09-23 20:12:32.837  16002-16002/com.urbanpro.seeker E/ROBOSPICE﹕ initialzig spice manager
    09-23 20:12:32.860  16002-16002/com.urbanpro.seeker E/ROBOSPICE﹕ Executing the method
    09-23 20:12:33.537  16002-16002/com.urbanpro.seeker E/ROBOSPICE﹕ on SUcceess
    09-23 20:12:33.553  16002-16002/com.urbanpro.seeker E/ROBOSPICE﹕ gettting the all contents
    09-23 20:12:33.601  16002-21819/com.urbanpro.seeker E/RETROFIT﹕ deseriazation starts
    09-23 20:12:33.603  16002-21819/com.urbanpro.seeker E/RETROFIT﹕ deseriazation ends
    

    RoboSpice现在已经过时。 - Mohamed Salah

    2
    另外一个选项是:https://github.com/apptik/jus
    • 它像Volley一样模块化,但更加扩展,并且文档正在改进,支持不同的HTTP堆栈和转换器。
    • 它有一个模块来生成类似于Retrofit的服务器API接口映射。
    • 它还支持JavaRx。

    还有许多其他方便的功能,如标记、转换器等。


    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接