本文由掘金翻译计划「https://github.com/xitu/gold-miner」投稿,译者Brucezz,可点击「阅读原文」查看原文链接。

在为可汗学院开发 Android app 时,OkHttp 是一个很重要的开源库。虽然它的默认配置已经提供了很好的效果,但是我们还是采取了一些措施提高 OkHttp 的可用性和自我检查能力:

1. 在文件系统中开启响应缓存

有些响应消息通过包含 Cache-Control HTTP 首部字段允许缓存,但是默认情况下,OkHttp 并不会缓存这些响应消息。因此你的客户端可能会因为不断请求相同的资源而浪费时间和带宽,而不是简单地读取一下首次响应消息的缓存副本。

为了在文件系统中开启响应缓存,需要配置一个 com.squareup.okhttp.Cache 实例,然后把它传递给 OkHttpClient 实例的 setCache 方法。你必须用一个表示目录的 File 对象和最大字节数来实例化 Cache 对象。那些能够缓存的响应消息会被写在指定的目录中。如果已缓存的响应消息导致目录内容超过了指定的大小,响应消息会按照最近最少使用(LRU Policy)的策略被移除。

正如 Jesse Wilson 所建议的,我们将响应消息缓存在 context.getCacheDir() 的子文件夹中:

// 缓存根目录,由这里推荐 -> http://stackoverflow.com/a/32752861/400717.
// 小心可能为空,参考下面两个链接
// https://groups.google.com/d/msg/android-developers/-694j87eXVU/YYs4b6kextwJ 和
// http://stackoverflow.com/q/4441849/400717.
final @Nullable File baseDir = context.getCacheDir();
if (baseDir != null) {  final File cacheDir = new File(baseDir, "HttpResponseCache");  okHttpClient.setCache(new Cache(cacheDir, HTTP_RESPONSE_DISK_CACHE_MAX_SIZE));
}

在可汗学院的应用中,我们指定了 HTTP_RESPONSE_DISK_CACHE_MAX_SIZE 的大小为 10 * 1024 * 1024,即 10MB。

2. 集成 Stetho

Stetho 是一个 Facebook 出品的超赞的开源库,它可以让你用 Chrome 的功能——开发者工具 来检查调试你的 Android 应用。

Stetho 不仅能够检查应用的 SQLite 数据库和视图层次,还可以检查 OkHttp 的每一条请求和响应消息:

这种自我检查方式(Introspection)有效地确保了服务器返回允许缓存资源的 HTTP 首部时,且核缓存资源存在时,不再发出任何请求。

开启 Stetho,只用简单地添加一个 StethoInterceptor 实例到网络拦截器(Network Interceptor)的列表中去:

okHttpClient.networkInterceptors().add(new StethoInterceptor());

应用运行完毕之后,打开 Chrome 然后跳转到 chrome://inspect。设备、应用以及应用标识符信息会被陈列出来。直接点击“inspect”链接就可以打开开发者工具,然后切换到 Network 标签开始监测 OkHttp 发出的请求。

3. 使用 Picasso 和 Retrofit

可能和我们一样,你使用 Picasso 来加载网络图片,或者使用 Retrofit 来简化网络请求和解析响应消息。在默认情况下,如果你没有显式地指定一个 OkHttpClient,这些开源库会隐式地创建它们自己的 OkHttpClient 实例以供内部使用。以下代码来自于 Picasso 2.5.2 版本的 OkHttpDownloader 类:

private static OkHttpClient defaultOkHttpClient() {  OkHttpClient client = new OkHttpClient();  client.setConnectTimeout(Utils.DEFAULT_CONNECT_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);  client.setReadTimeout(Utils.DEFAULT_READ_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);  client.setWriteTimeout(Utils.DEFAULT_WRITE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);  return client;
}

Retrofit 也有类似的工厂方法用来创建它自己的 OkHttpClient。

图片是应用中需要加载的最大的资源之一。Picasso 是严格地按照 LRU 策略在内存中维护它的图片缓存。如果客户端尝试用 Picasso 加载一张图片,并且 Picasso 没有在内存缓存中找到该图片,那么它会委托内部的 OkHttpClient 实例来加载该图片。在默认情况下,由于前面的 defaultOkHttpClient 方法没有在文件系统中配置响应缓存,该实例会一直从服务器加载图片。

自定义一个 OkHttpClient 实例,将从文件系统返回一个已缓存的响应消息这种情况考虑在内。没有一张图片直接从服务器加载。这在应用第一次加载时是尤为重要的。在这个时候,Picasso 的内存中的缓存是 “冷”的,它会频繁地委托 OkHttpClient 实例去加载图片。

这就需要构建一个用你的 OkHttpClient 配置的 Picasso 实例。如果你在代码中使用 Picasso.with(context).load(...) 来加载图片,你所使用的 Picasso 单例对象,是在 with 方法中用自己的 OkHttpClient 延迟加载和配置的。因此我们必须在第一次调用 with 方法之前指定自己的 Picasso 实例作为单例对象。

简单地把 OkHttpClient 实例包装到一个 OkHttpDownloader 对象中,然后传递给 Picasso.Builder 实例的 downloader 方法:

final Picasso picasso = new Picasso.Builder(context)    .downloader(new OkHttpDownloader(okHttpClient))    .build();
//客户端应该在任何需要的时候来创建这个实例
//以防万一,替换掉那个单例对象
Picasso.setSingletonInstance(picasso);

在 Retrofit 1.9.x 中,通过 RestAdapter 使用你的 OkHttpClient 实例,把 OkHttpClient 实例包装到一个 OkClient 实例中,然后传递给 RestAdapter.Builder 实例的 setClient 方法:

restAdapterBuilder.setClient(new OkClient(httpClient));

在 Retrofit 2.0 中,直接把 OkHttpClient 实例传递给 Retrofit.Builder 实例的 client 即可。

在可汗学院的应用中,我们使用 Dagger 来确保只有一个 OkHttpClient 实例,而且 Picasso 和 Retrofit 都会使用到它。我们为带 @Singleton 注解的 OkHttpClient 实例创建了一个 provider:

@Provides
@Singleton
public OkHttpClient okHttpClient(final Context context, ...) {  final OkHttpClient okHttpClient = new OkHttpClient();  configureClient(okHttpClient, ...);  return okHttpClient;
}

这个 OkHttpClient 实例随后通过 Dagger 注入到其他用来创建 RestAdapter 和 Picasso 实例的 provider 里。

4. 设置用户代理拦截器(User-Agent Interceptor)

当客户端在每一次请求中都提供一个详细的 User-Agent 头部信息时,日志文件和分析数据提供了很有用的信息。默认情况下,OkHttp 的 User-Agent 值仅仅只有它的版本号。要设定你自己的 User-Agent,创建一个拦截器(Interceptor)然后替换掉默认值,参考 StackOverflow 上的建议:

public final class UserAgentInterceptor implements Interceptor {  private static final String USER_AGENT_HEADER_NAME = "User-Agent";  private final String userAgentHeaderValue;  public UserAgentInterceptor(String userAgentHeaderValue) {    this.userAgentHeaderValue = Preconditions.checkNotNull(userAgentHeaderValue);  }  @Override  public Response intercept(Chain chain) throws IOException {    final Request originalRequest = chain.request();    final Request requestWithUserAgent = originalRequest.newBuilder().removeHeader(USER_AGENT_HEADER_NAME)       .addHeader(USER_AGENT_HEADER_NAME, userAgentHeaderValue).build();    return chain.proceed(requestWithUserAgent);  }}

使用任何你觉得有价值的信息,来创建 User-Agent 值,然后传递给 UserAgentInterceptor 的构造函数。我们使用了这些字段:

  • os 字段,值设置为 Android,明确表明这是一个 Android 设备

  • Build.MODEL 字段,即用户可见的终端产品的名称

  • Build.BRAND 字段,即消费者可见的跟产品或硬件相关的商标

  • Build.VERSION.SDK_INT 字段,即用户可见的 [Android] 框架版本号

  • BuildConfig.APPLICATION_ID 字段

  • BuildConfig.VERSION_NAME 字段

  • BuildConfig.VERSION_CODE字段

最后三个字段是根据我们的 Gradle 构建脚本中的 applicationId, versionCode 和 versionName 的值来确定的。了解更多信息请参考文档 应用版本控制,和 使用 Gradle 配置你的 applicationId。

小提示:如果你的应用中用到了 WebView,你可以配置使用相同的 User-Agent 值,即之前创建的 UserAgentInterceptor:

WebSettings settings = webView.getSettings();settings.setUserAgentString(userAgentHeaderValue);

5. 指定合理的超时

在 2.5.0 版本之前,OkHttp 请求默认永不超时。从 2.5.0 版本开始,如果建立了一个连接,或从连接读取下一个字节,或者向连接写入下一个字节,用时超过了10秒,请求就会超时。分别调用 setConnectTimeout,setReadTimeout 或 setWriteTimeout 方法可以重写那些默认值。

小提示:Picasso 和 Retrofit 为它们的默认 OkHttpClient 实例指定不同的超时时长。 默认情况下, Picasso 设定如下:

  • 连接超时15秒

  • 读取超时20秒

  • 写入超时20秒

Retrofit 设定如下:

  • 连接超时15秒

  • 读取超时20秒

  • 写入无超时

用你自己的 OkHttpClient 实例配置好 Picasso 和 Retrofit 之后,就能确保所有请求超时的一致性了。

结论

再次强调,OkHttp 的默认配置提供了显著的效果,但是采取以上的措施,可以提高 OkHttp 的可用性和自我检查能力,并且提升你的应用的质量。

觉得有帮助不妨转发支持下,长按二维码可订阅。

推荐阅读:

我为什么坚持写博客?

Android 学习资料收集

如何更高效地使用 OkHttp相关推荐

  1. 这些小工具让你的Android 开发更高效

    在做Android 开发过程中,会遇到一些小的问题,虽然自己动手也能解决,但是有了一些小工具,解决这些问题就得心应手了,今天就为大家推荐一下Android 开发遇到的小工具,来让你的开发更高效. Vy ...

  2. java游戏开发--连连看-让程序运行更稳定、更高效

    之六)优化:让程序运行更稳定.更高效 改善游戏的合理性 到目前为止,我们的游戏基本上算是完成了,为了使程序更合理,我们还需要将整个程序从头再理一遍,看看有没有改进的地方. 首先,在变量的使用上,由于很 ...

  3. 推荐8个非常有逼格的实用软件,让你的办公更高效

    推荐8个非常有逼格,并且极其实用的软件,解决你很多需求,让职场办公更高效. 1.Billfish Billfish可以快速.轻松管理各种设计素材,让你更专注于设计本身.软件支持Windows和macO ...

  4. 推荐10个windows软件,让你的办公更高效

    1.Flomo Flomo 是一款让你更好思考的笔记软件,含义是流动的笔记.它的理念是:重要的不是记录,而是更好地思考.Flomo 非常的轻量化:空间很轻.编辑很轻.分享很轻,可以让你捕捉灵感.记录日 ...

  5. 更高效的PacBio长read纠错算法的研究

    更高效的PacBio长read纠错算法的研究 更高效的PacBio长read纠错算法的研究 中文摘要 第三代PacBio测序技术的长read已越来越广泛的应用于各类测序项目中,而降低其约15%的错误率 ...

  6. 最常用的10个Matlab快捷键,助你编程更高效

    本文转载:最常用的10个Matlab快捷键,助你编程更高效 目录 1. 屏蔽大段程序:Ctrl+r 2. 自动对齐程序:Ctrl+i 3. 直接跳至某行:Ctrl+g 4. 设置标签:Ctrl+F2 ...

  7. Adaptive Execution让Spark SQL更高效更好用

    本文所述内容均基于 2018年9月17日 Spark 最新 Spark Release 2.3.1 版本,以及截止到 2018年10月21日 Adaptive Execution 最新开发代码.自动设 ...

  8. 英语和汉语谁更高效?17大主流语言测试结果:没有优劣之分,带宽都是每秒39bit...

    晓查 发自 凹非寺 量子位 出品 | 公众号 QbitAI 哪种语言是世界上最高效的语言?这个问题一直争论不休,也难以量化. 首先,不同语种的说话速度差异很大.有研究证明,意大利人语速最快,每秒能说9 ...

  9. 面试mysql中怎么创建索引_阿里面试:MySQL如何设计索引更高效?

    有情怀,有干货,微信搜索[三太子敖丙]关注这个不一样的程序员. 本文 GitHub https://github.com/JavaFamily 已收录,有一线大厂面试完整考点.资料以及我的系列文章. ...

  10. MaxCompute2.0性能评测:更强大、更高效之上的更快速

    原文链接:http://click.aliyun.com/m/13999/MaxCompute2.0(原Odps):通过性能评测,MaxCompute2.0离线计算比同类产品Hive2.0 on Te ...

最新文章

  1. 英伟达PyTorch优化神器TensorRT重磅更新!10亿参数大模型实时运行,GPT推理加速21倍...
  2. R语言基于LASSO进行特征筛选(feature selection)
  3. python opengl 入门
  4. 只想多吃,而不考虑能吃掉多少——如何恰到好处的按需进度规划?
  5. Spring Boot-Spring Tool Suit + Gradle 构建第一个Spring Boot 项目02
  6. 微软 PowerBI 被评为商业智能领导者-13年的企业产品奋斗史解读
  7. java依赖注入_Java依赖注入选项
  8. 帆软按钮控件变查询_帆软报表(多sheet)自定义分页查询
  9. 【英语学习】【Level 08】U02 Movie Time L6 Blockbuster
  10. python chardet_Python - chardet
  11. 力扣-135 分发糖果
  12. 笔记本电脑VGA与DVI接口的区别(转)
  13. 实习成长之路:MySQL九:为什么MySQL有时候会选错索引呢?
  14. C#程序员整理的Unity 3D笔记(十三):Unity 3D基于组件的思想
  15. qq pc9.4协议机器人框架源码
  16. 基因组数据质控中:先进行SNP缺失质控还是样本缺失质控?
  17. 2022N1叉车司机题库及在线模拟考试
  18. TortoiseGit assume-unchanged的文件怎么恢复
  19. 消防装备管理心得体会
  20. 微信小程序使用云函数进行mysql操作

热门文章

  1. java基础七--网络编程(1)
  2. java基础知识补漏(1)---内部类,重写、重载
  3. 提高查询效率,了解SQL的索引管理规则
  4. 来告诉大家 AddressSanitizer: stack-buffer-overflow on address 一般都是代码哪里出现了问题
  5. 如何自动清理从 Mac 到 Dropbox 的屏幕截图?
  6. FontExplorer X Pro for Mac字体管理软件
  7. 经常会用到的ocr文字识别工具:Text Scanner for Mac
  8. 马斯克宣布退出OpenAI,全身心投入特斯拉与SpaceX
  9. Java经典设计模式 总览
  10. 循环语句—C#基础回顾