Android上使用retrofit+okhttp时token失效的处理方案

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android上使用retrofit+okhttp时token失效的处理方案相关的知识,希望对你有一定的参考价值。

参考技术A 提前声明,以下提到的方案并没有去验证过可行性,只是记录一下,未来需要用到的时候,在仔细验证一下。

一般情况下,各个公司的移动端关于登录令牌(token)的设定都各不相同。

可先参考这个链接: https://www.zhihu.com/question/30267006

了解一下,本文大概想说什么。

有些公司服务端是按照oauth设计,比较标准规范,但是有些公司有自己的特定业务,未完全按照oauth来设计。基于本公司的业务逻辑,考虑了一下登录的逻辑以及token的设计。

思路如下:

token即验证令牌,每次请求都带上,refreshToken用来刷新token的,每次请求可以不带上,但是要放在移动端保存。

1.通过username,password获取token和refreshToken

2.token的有效期为2小时,refreshToken的有效期为15天

3.如果服务器端判断token过期,而refreshToken未过期,就返回错误码给客户端,则客户端通过一个特定的接口传入refreshToken参数获取新的token和refreshToken

4.如果连续15天未使用app或者用户修改了密码,则表示refreshToken过期了,则跳到登录界面,重新登录获取token和refreshToken

基于上面的思路,如果服务端走rest风格,移动端(android)采用retrofit(v2.0+)+okhttp(v2.7.0+)网络请求框架。那么当token过期了,Android端应该如何处理呢?

通过okhttp提供的Authenticator接口,相关资料 点击这里 ,但是查看okhttp的源码会发现,只有返回HTTP的状态码为401时,才会使用Authenticator接口,如果服务端设计规范,可以尝试如下方法。

实现Authenticator接口

然后给添加给OkHttpClient

第一种方案就这样了。

但是,万事不会尽如人意,如果服务端在token过期的时候,不给返回401的HTTP状态码,而是返回如下类型的数据,叫你根据code判断。

这里要清楚HTTP状态码是指200,404,401这些,而上面的数据中的code是自定义的。如果在token过期时,服务端返回的是如上类型的数据,那么第一种方案就行不通。

通过okhttp的拦截器,okhttp 2.2.0 以后提供了拦截器的功能,相关介绍 点击这里

然后给okhttp设置拦截器

第二种方案的思路是通过拦截返回的数据,判断token是否过期,如果过期则进行一次刷新token的操作。

上面2种方案都没有进行实际验证过,希望以后有机会能验证。

完。。。

Android 网络库的比较:OkHTTP、Retrofit 和 Volley [关闭]

【中文标题】Android 网络库的比较:OkHTTP、Retrofit 和 Volley [关闭]【英文标题】:Comparison of Android networking libraries: OkHTTP, Retrofit, and Volley [closed] 【发布时间】:2017-06-25 15:51:15 【问题描述】:

一位学习 Android 的 iOS 开发人员提出的两部分问题,他正在开发一个 Android 项目,该项目将提出各种请求,从 JSON 到图像再到音频和视频的流式下载:

    在 iOS 上,我广泛使用了 AFNetworking 项目。是否有适用于 Android 的等效库?

    我已经阅读了 Square 的 OkHTTP 和 Retrofit 以及 Volley,但还没有与他们一起开发的经验。我希望有人可以为每个人提供一些最佳用例的具体示例。根据我的阅读,OkHTTP 似乎是三者中最健壮的,并且可以处理这个项目的要求(如上所述)。

【问题讨论】:

如果您使用 HttpUrlConnection 的内部实现,您应该考虑到 HttpUrlConnection 对 POST 请求使用静默重试。这对我造成了很大的伤害。欲了解更多信息,请阅读此处:***.com/a/37675253/2061089 如果有人需要所有网络库的列表,您可以在我的博文androidredman.wordpress.com/2017/06/26/…中找到它 Volley 可以运行传统的 Apache、HttpUrlConnection、Apache-4 或 OkHttp。 Retrofit 在哪里真的只运行 OkHttp。改造更容易配置。 【参考方案1】:

我希望有人可以为每个人提供一些最佳用例的具体示例。

如果您正在与 Web 服务通信,请使用 Retrofit。如果您正在下载图像,请使用对等库 Picasso。如果您需要执行 Retrofit/Picasso 之外的 HTTP 操作,请使用 OkHTTP。

Volley 与 Retrofit + Picasso 大致竞争。从好的方面来说,它是一个图书馆。不利的一面是,它是 一个未记录的, 一个不受支持的“将代码扔到墙上并在其上进行 I|O 演示”的库。

编辑 - Volley 现在得到 Google 的正式支持。请参考Google Developer Guide

根据我的阅读,OkHTTP 似乎是 3 个中最健壮的

如果可用,Retrofit 会自动使用 OkHTTP。有一个Gist from Jake Wharton 将 Volley 连接到 OkHTTP。

并且可以处理这个项目的要求(如上所述)。

按照“流式传输”的传统定义,您可能不会将它们用于“音频和视频的流式下载”。相反,Android 的媒体框架会为您处理这些 HTTP 请求。

话虽如此,如果您要尝试进行自己的基于 HTTP 的流式传输,OkHTTP 应该可以处理这种情况;我不记得 Volley 会如何处理这种情况。 Retrofit 和 Picasso 都不是为此而设计的。

【讨论】:

感谢@CommonsWare 的简明回答,以及关于 Volley 无证 steez 的注释(得到了这样的印象,尤其是与其他项目相比)。绝对可以帮助我把事情做好。 @CommonsWare 的另一个很好的回答。有人可以跟进 RoboSpice 如何融入所有这些吗? @user1923613 github.com/octo-online/robospice 如果您使用 volley 进行网络调用,则无需使用 robospice!,volley 完成了 Robospice 为网络调用所做的许多事情,Robospice 开箱即用地支持 REST (使用 Spring Android 或 Google Http Client 或 Retrofit)。如果您想通过强大的网络客户端快速联网和图像加载,您可以选择 volley!但是您可以替换使用 Robospice 的普通 android 异步任务以获得更好的性能并避免内存泄漏! @frostymarvelous:我觉得无证和不受支持的理由绰绰有余。谷歌并不是缺少一个系统来更正式地处理这样的事情(例如,Android 支持库)。在这个答案之后的两年里,从好的方面来说,有一些社区支持,包括将一些非官方的代码打包成一个工件。 @AbhinavVutukuri:您正在评论两年多前的答案。当时还没有文档。【参考方案2】:

从 Volley 的角度来看,这里有一些满足您要求的优势:

一方面,Volley 完全专注于处理单个的小型 HTTP 请求。因此,如果您的 HTTP 请求处理有一些怪癖,Volley 可能会为您提供一个钩子。另一方面,如果您在图像处理方面有一个怪癖,那么唯一真正的钩子就是 ImageCache。 “这不是什么都没有,但也不是很多!”。但它还有更多其他优势,例如一旦定义了请求,就可以在片段或活动中使用它们,这与并行 AsyncTask 不同

Volley 的优缺点:

那么 Volley 有什么好处呢?

网络部分不仅仅用于图像。排球的目的是 后端的一个组成部分。对于一个基于 简单的 REST 服务,这可能是一个巨大的胜利。

NetworkImageView 在请求清理方面比 Picasso,并且在其 GC 使用模式上更加保守。 NetworkImageView 完全依赖于强内存引用,并且 一旦对 ImageView,或者只要 ImageView 移出屏幕。

性能。这篇文章不会评估这种说法,但他们已经清楚 在他们的内存使用模式上采取了一些谨慎的态度。 Volley 还努力批量回调到主线程以 减少上下文切换。

Volley 显然也有未来。如果您是,请查看 RequestFuture 有兴趣。

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

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

Volley 在 Activity 生命周期中表现出色。

排球问题: 由于 Volley 是新的,因此尚不支持一些东西,但它已修复。

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

    状态码 201 被视为错误,状态码 200 到 207 现在是成功响应。(固定:https://github.com/Vinayrraj/CustomVolley)

    更新:在最新版本的 Google volley 中,2XX 状态码错误现在是 fixed!感谢 Ficus Kirkpatrick!

    文档较少,但很多人都支持 github 中的 volley,可以在 here 找到类似 java 的文档。 在 android 开发者网站上,您可以找到Transmitting Network Data Using Volley 的指南。并且volley源码可以在Google Git

    找到

    要解决/更改Redirect Policy of Volley 框架使用Volley with OkHTTP(上面提到的CommonsWare)

你也可以阅读这个Comparing Volley's image loading with Picasso

改造:

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

改造的优点:

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

我们可以将它与任何带有错误处理的序列化库一起使用。

更新: - Retrofit 2.0.0-beta2 有很多非常好的变化

Retrofit with OkHttp 2.0 的 1.6 版现在依赖于 Okio 来支持 java.iojava.nio 这使得它使用 ByteStringBuffer 可以更轻松地访问、存储和处理您的数据,从而节省 CPU 和内存。 (仅供参考:这让我想起了支持 NIO 的 Koush's OIN 库!) 我们可以使用Retrofit together with RxJava 来组合和链接REST 调用,使用rxObservables 来避免丑陋的回调链(避免回调地狱!!)

1.6 版改造的缺点:

与内存相关的错误处理功能不好(在旧版本的 Retrofit/OkHttp 中)不确定它是否通过支持 Java NIO 的 Okio 得到了改进。

如果我们使用这个,最小的线程辅助可能会导致回调地狱 以不正当的方式。

(以上所有Cons都已在新版Retrofit 2.0 beta中解决)

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

更新:

Android Async vs Volley vs Retrofit 性能基准(毫秒,值越低越好):

(仅供参考,上面的 Retrofit Benchmarks 信息将通过 java NIO 支持得到改进,因为新版本的 OKhttp 依赖于 NIO Okio 库)

在所有三个重复次数不同(1 到 25 次)的测试中,Volley 速度从 50% 到 75% 不等。改造以令人印象深刻的速度进行 比 AsyncTask 快 50% 到 90%,到达相同的端点 相同的次数。在仪表板测试套件上,这已翻译 更快地加载/解析数据几秒钟。这是一个 巨大的现实世界差异。为了使考试公平, AsyncTasks/Volley 的时间包括 JSON 解析,就像 Retrofit 一样 它会自动为您服务。

RetroFit 在基准测试中获胜!

最后,我们决定为我们的应用程序使用 Retrofit。不是 只是速度快得离谱,但它与我们的 现有架构。我们能够进行父回调 自动执行错误处理、缓存和 分页对我们的 API 几乎没有任何努力。为了融入 改造,我们必须重命名我们的变量以使我们的模型 GSON 合规,写几个简单的接口,删除函数 旧 API,并修改我们的片段以不使用 AsyncTasks。现在我们 有几个片段完全转换,这很无痛。那里 是一些成长的痛苦和我们必须克服的问题,但是 总体来说进展顺利。一开始,我们遇到了几个 技术问题/错误,但 Square 有一个很棒的 Google+ 社区 这能够帮助我们度过难关。

什么时候使用 Volley?!

当我们需要加载图像以及使用 REST API 时,我们可以使用 Volley!,网络调用队列系统需要同时处理许多 n/w 请求! Volley 也比 Retrofit 有更好的内存相关错误处理!

OkHttp可以和Volley一起使用,Retrofit默认使用OkHttp!它具有SPDY 支持、连接池、磁盘缓存、透明压缩!最近,它通过 Okio 库获得了对 java NIO 的一些支持。

来源,来源:volley-vs-retrofit Josh Ruesch 先生

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

【讨论】:

@Jan1337z +1 获取信息!我已经更新了!android.googlesource.com/platform/frameworks/volley @LOG_TAG 在您的示例中对 RoboSpice 进行基准测试会很有趣。我们甚至提供了一个改造模块,所以我相信这需要很少的改动。来源在某处可用吗? RS 的优点是可以正确处理执行网络请求的活动的生命周期,并且我们还提供透明缓存,我想与纯粹的改造请求相比开销会很小。 @Snicolas 我得到了 Josh Ruesch blog 的基准测试结果,您可以看到 Ficus Kirkpatrick(Volley 创始人)和 Josh Ruesch 之间的转换!他还没有在任何地方共享基准测试项目!仅供参考,我刚刚开始学习您的 RoboSpice with retrofit sample 面对此通知 issue :) 嗨!关于 Volley 的 Multipart Requests,我认为我们可以在 httpmime 库中使用 MultipartEntityBuilder 有其他人验证过这些基准吗?由于 M 中不推荐使用 apache http 库(并且我将它用于多部分构建器),我决定将我的网络代码迁移到 Retrofit。我最初更改了一个 GET 调用以从服务器获取一堆对象。我对 Retrofit 与 AsyncTask 进行了计时(使用我自己的 JSON 解析)。性能非常接近,而不是表中“一次讨论”列中显示的 3 倍改进。诚然,生成的代码更简洁,我不必编写自己的 JSON 解析器,但对于单个 GET 请求,改进并不存在。【参考方案3】:

RoboSpice 对比。凌空抽射

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

RoboSpice(RS) 是基于服务的,比 Volley 更尊重 Android 理念。 Volley 是基于线程的,这不是在 Android 上进行后台处理的方式。最终,您可以深入挖掘这两个库并发现它们非常相似,但我们进行后台处理的方式更面向 Android,例如,它允许我们告诉用户 RS 实际上在后台做某事,这将是凌空抽射很困难(实际上一点也不)。 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 可以与 ok http 一起使用并使用 gson。就是这样。 Volley 提供了比 RS 更多的 UI 糖。 Volley 提供 NetworkImageView,RS 确实提供了一个 spicelist 适配器。就功能而言,目前还没有,但我相信 Volley 在这个主题上更先进。 自 RoboSpice 首次发布以来,已解决了 200 多个错误。它非常健壮,并在生产中大量使用。 Volley 不太成熟,但它的用户群应该会快速增长(谷歌效应)。 RoboSpice 在 maven Central 上可用。排球很难找到;)

【讨论】:

Robospice 使用 android 服务进行 REST 调用,我们可以使用 Robospice 和 Retrofit 来最小化 gson 解析工作,就像我们可以使用 Volley(基于胎面)和 Robospice 一样? (不知道问的qsn是否正确)我只是在寻找凌空服务! 带服务的排球基本上是RS。或者,按时间顺序,Volley 是没有服务且缺少其他功能的 RS。是的,您可以将 Retrofit 与 RS 一起使用,如果您愿意,甚至可以添加 okhttp。 为什么凌空难找? compile 'com.mcxiaoke.volley:library:1.0.+' @Rob 曾经有一段时间,mcxiaoke 的克隆不可用。您必须在应用中手动包含 volley。 "volley 将反序列化主线程上的 POJO"。如果这是一个问题,您可以接收返回的 JSON 数据并在单独的线程上自行反序列化。【参考方案4】:

AFNetworking for Android:

Fast Android Networking 是here

Fast Android Networking Library 支持所有类型的 HTTP/HTTPS 请求,例如 GET、POST、DELETE、HEAD、PUT、PATCH

Fast Android Networking Library 支持下载任何类型的文件

Fast Android Networking Library 支持上传任何类型的文件(支持分段上传)

Fast Android Networking Library 支持取消请求

Fast Android Networking Library 支持为任何请求设置优先级(LOW、MEDIUM、HIGH、IMMEDIATE)

快速 Android 网络库支持 RxJava

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

Fast Android Networking Library 支持 HTTP/2 支持允许对同一主机的所有请求共享一个套接字

Fast Android Networking Library 使用连接池来减少请求延迟(如果 HTTP/2 不可用)

透明 GZIP 缩小下载大小

Fast Android Networking Library 支持响应缓存,完全避免网络重复请求

谢谢:图书馆是我创建的

【讨论】:

您声明您的库支持 HTTP/2,但您没有说是否有 API 要求支持 HTTP/2。我的理解是,低于 5.0 的 Android API 级别没有正确的 SSL 加密方法来支持 HTTP/2。不敲门,只是想全面评估您提出的解决方案。 @AmitShekhar:我只是想知道哪一个最适合 Android 中的 API 调用。我正在使用 Android Networking Library,那么哪个更适合实现 Retrofit、Volley 或 Android Networking? @Amit Shekhar 快速 Android 网络对于多部分图像上传的效率如何,尤其是在低互联网场景下?【参考方案5】:

异步 HTTP 客户端循环与 Volley

我的项目的细节是小型 HTTP REST 请求,每 1-5 分钟一次。

我长期使用异步 HTTP 客户端 (1.4.1)。性能优于使用 vanilla Apache httpClient 或 HTTP URL 连接。无论如何,新版本的库对我不起作用:library inter exception cut chain of callbacks.

阅读所有答案促使我尝试新事物。我选择了 Volley HTTP 库。

使用一段时间后,即使没有测试,我也清楚地看到响应时间下降到 1.5x,2x Volley。

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

【讨论】:

关于 Retrofit Vs AsyncHttpClient 的任何分析 ???如果是,请发布@Sergey instructure.github.io/blog/2013/12/09/volley-vs-retrofit 我使用 AsyncHttpClient 已经有几年了。不好的部分是 github repo 有 2 年没有提交。 它不再是实际的了,异步 http 太老了。考虑换一个库。排球也成为了非常不错的选择。 Sergey,@IshRoid 我仍在寻找您的问题的答复/跨度> 【参考方案6】:

根据我使用 Volley 的经验来补充一点讨论:

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

    官方文档的缺失很烦人,尽管我已经能够通过阅读源代码来解决这个问题,这很容易理解。更麻烦的是,据我所知,Volley 没有官方发布版本,也没有 Maven 或 Gradle 工件,因此将其作为依赖项进行管理变得比 Square 发布的任何库更令人头疼.您只需克隆一个 repo,构建一个 jar,然后您就可以靠自己了。寻找错误修复?获取并希望它在那里。你也可能得到一些其他的东西;它不会被记录在案。在我看来,这实际上意味着 Volley 是一个不受支持的 3rd 方库,即使代码库相当活跃。警告购买者。

    总的来说,将 Content-Type 绑定到类/请求类型(JsonObjectRequest、ImageRequest 等)有点尴尬,并且会降低调用代码的灵活性,因为您需要绑定Volley 现有的请求类型层次结构。我喜欢直接将 Content-Type 设置为与其他任何标题一样的标题(顺便说一下,不要对 Volley 进行此操作;您最终会得到两个 Content-Type 标题!)。不过,这只是我的个人意见,可以解决。

这并不是说 Volley 没有一些有用的功能。确实如此。易于定制的重试策略、透明缓存、取消 API 以及对请求调度和并发连接的支持都是很棒的功能。只需知道它并不适用于所有 HTTP 用例(请参阅上面的第 1 项),并且在您的应用中将 Volley 投入生产使用(第 2 项)会涉及一些令人头疼的问题。

【讨论】:

完整的内存加载是我慢慢杀死我的原因。感谢上帝,其他人提到了它。 该库还可能会为您的请求正文制作一份防御性副本,因此大型请求的内存消耗可能是您预期的两倍。【参考方案7】:

我最近发现了一个名为ion 的库,它为桌面带来了一些额外的东西。

ion 内置支持与 ImageView、JSON(在 GSON 的帮助下)、文件和非常方便的 UI 线程支持集成的图像下载。

我在一个新项目中使用它,到目前为止效果很好。它的使用比 Volley 或 Retrofit 简单得多。

【讨论】:

ion vs retrofit,你会推荐哪一个? 改造比离子好【参考方案8】:

除了已接受的答案和 LOG_TAG 所说的内容之外......为了让 Volley 在后台线程中解析您的数据,您必须将 Request<YourClassName> 子类化,因为在主线程上调用 onResponse 方法并在主线程上解析如果您的响应很大,可能会导致 UI 滞后。 阅读here 了解如何做到这一点。

【讨论】:

对... volley 解析主线程上的响应,当响应非常大时会导致用户滞后。【参考方案9】:

改造 1.9.0 与 RoboSpice

我在我的应用程序中同时使用这两种方法。

每当我解析嵌套的 JSON 类时,Robospice 的运行速度都比 Retrofit 快。因为 Spice Manger 会为您做一切。在 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 现已过时。【参考方案10】:

还有另一种选择: https://github.com/apptik/jus

它像 Volley 一样是模块化的,但扩展性更强,文档也在改进,支持开箱即用的不同 HTTP 堆栈和转换器 它有一个生成服务器 API 接口映射的模块,例如 Retrofit 它还支持 JavaRx

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

【讨论】:

以上是关于Android上使用retrofit+okhttp时token失效的处理方案的主要内容,如果未能解决你的问题,请参考以下文章

Android 网络库的比较:OkHTTP、Retrofit 和 Volley [关闭]

Android上使用retrofit+okhttp时token失效的处理方案

Retrofit+Okhttp 在 Android 中是不是默认使用 httpCaching?

学会Retrofit+OkHttp+RxAndroid三剑客的使用,让自己紧跟Android潮流的步伐

如何使用 OkHttp/Retrofit 重试 HTTP 请求?

android之Retrofit使用