OkHttp缓存配置

作者: TrancyDeng | 来源:发表于2016-06-04 18:02 被阅读2562次

前言

废话不多说,先奉上
OkHttp GitHub

说到OKHTTP,我想你肯定不会陌生,Android中无数大大小小的项目在用这个开源库,甚至包括Google开发的一些项目也在用。Android API23 抛弃了httpclient之后,我想肯定会有很多人在为寻找下一个好用的网络库而犯愁。看到这里,我认为你走对了。

OkHttp使用的几种方式

OkHttp的性能我自不必说,关于使用方式(异步GET,同步GET...)自不必说,网上资料非常多。在这里我直接贴出代码。

同步get

下载一个文件,打印他的响应头,以string形式打印响应体。
  响应体的 string() 方法对于小文档来说十分方便、高效。但是如果响应体太大(超过1MB),应避免适应 string()方法 ,因为他会将把整个文档加载到内存中。对于超过1MB的响应body,应使用流的方式来处理body。

private final OkHttpClient client = new OkHttpClient();

public void run() throws Exception {
    Request request = new Request.Builder()
        .url("http://publicobject.com/helloworld.txt")
        .build();

    Response response = client.newCall(request).execute();
    if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);

    Headers responseHeaders = response.headers();
    for (int i = 0; i < responseHeaders.size(); i++) {
      System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i));
    }

    System.out.println(response.body().string());
}

异步get

在一个工作线程中下载文件,当响应可读时回调Callback接口。读取响应时会阻塞当前线程。OkHttp现阶段不提供异步api来接收响应体。

private final OkHttpClient client = new OkHttpClient();

public void run() throws Exception {
    Request request = new Request.Builder()
        .url("http://publicobject.com/helloworld.txt")
        .build();

    client.newCall(request).enqueue(new Callback() {
      @Override public void onFailure(Request request, Throwable throwable) {
        throwable.printStackTrace();
      }

      @Override public void onResponse(Response response) throws IOException {
        if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);

        Headers responseHeaders = response.headers();
        for (int i = 0; i < responseHeaders.size(); i++) {
          System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i));
        }

        System.out.println(response.body().string());
      }
    });
}

Post方式提交String

使用HTTP POST提交请求到服务。这个例子提交了一个markdown文档到web服务,以HTML方式渲染markdown。因为整个请求体都在内存中,因此避免使用此api提交大文档(大于1MB)。

public static final MediaType MEDIA_TYPE_MARKDOWN
  = MediaType.parse("text/x-markdown; charset=utf-8");

private final OkHttpClient client = new OkHttpClient();

public void run() throws Exception {
    String postBody = ""
        + "Releases\n"
        + "--------\n"
        + "\n"
        + " * _1.0_ May 6, 2013\n"
        + " * _1.1_ June 15, 2013\n"
        + " * _1.2_ August 11, 2013\n";

    Request request = new Request.Builder()
        .url("https://api.github.com/markdown/raw")
        .post(RequestBody.create(MEDIA_TYPE_MARKDOWN, postBody))
        .build();

    Response response = client.newCall(request).execute();
    if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);

    System.out.println(response.body().string());
}

Post方式提交文件

直接封装好文件体就可以

public static final MediaType MEDIA_TYPE_MARKDOWN
  = MediaType.parse("text/x-markdown; charset=utf-8");

private final OkHttpClient client = new OkHttpClient();

public void run() throws Exception {
    File file = new File("README.md");

    Request request = new Request.Builder()
        .url("https://api.github.com/markdown/raw")
        .post(RequestBody.create(MEDIA_TYPE_MARKDOWN, file))
        .build();

    Response response = client.newCall(request).execute();
    if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);

    System.out.println(response.body().string());
}

Post方式提交表单

估计这是一种最常用的方式了

private final OkHttpClient client = new OkHttpClient();

public void run() throws Exception {
    RequestBody formBody = new FormEncodingBuilder()
        .add("search", "Jurassic Park")
        .build();
    Request request = new Request.Builder()
        .url("https://en.wikipedia.org/w/index.php")
        .post(formBody)
        .build();

    Response response = client.newCall(request).execute();
    if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);

    System.out.println(response.body().string());
}

缓存策略

我当初在这方面卡了一些时间。这也是今天的重点。

<code>
File httpCacheDirectory = new File(pActivity.getExternalCacheDir(), "cache_zhiyixing");
</code>

首先创建文件缓存目录,这里有两个参数

new OkHttpClient.Builder()
                .connectTimeout(10, TimeUnit.SECONDS)
                .cache(new Cache(httpCacheDirectory, 1024 * 1024 * 10)).build();

通过OKHTTP的构建者模式把文件目录传入进去。运行之后,从外置存储中你会发现缓存目录已经创建完成。而且内容也已经缓存进去了。

断网,再次打开软件,发现并不能把缓存读取出来。
这是为什么呢?
  这是OKHTTP的缓存策略导致的。用户可以设置cache-control来控制缓存的时效。有关cache-control的介绍请戳这里,不能翻墙的戳这里

这里我把配置代码放上

package com.android.zhixing.model;

import android.content.Context;

import com.android.zhixing.utils.NetWorkUtils;
import com.socks.library.KLog;

import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

import okhttp3.Cache;
import okhttp3.CacheControl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

/**
 * Created by dengqiangxi on 16/5/30.
 */
public class OurOkHttpClient {

    public static OkHttpClient getClient(final Context pActivity) {
        File httpCacheDirectory = new File(pActivity.getExternalCacheDir(), "cache_zhiyixing");

        return new OkHttpClient.Builder()
                .connectTimeout(10, TimeUnit.SECONDS)
                .cache(new Cache(httpCacheDirectory, 1024 * 1024 * 10))
                .addInterceptor(new Interceptor() {
                    @Override
                    public Response intercept(Chain chain) throws IOException {
                        Request request = chain.request();
                        Log.e("新请求", "=request==" + request.toString());
                        Response response = chain.proceed(request);
                        if (NetWorkUtils.isNetworkReachable(pActivity)) {
                            int maxAge = 60 * 60*24; // 有网络的时候从缓存1天后失效
                            response.newBuilder()
                                    .removeHeader("Pragma")
                                .header("Cache-Control", "public, max-age=" + maxAge)
                                     .build();
                        } else {
                            int maxStale = 60 * 60 * 24 * 28; // // 无网络缓存保存四周
                            response.newBuilder()
                                    .removeHeader("Pragma")
                                    .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
                                    .build();
                        }
                        return response;
                    }
                })
                .build();

    }
}

至此,有关OKHTTP的相关配置就已经介绍完了,下一节将介绍OKHTTP和retrofit结合使用。

相关文章

  • OKHTTP之缓存配置详解

    本文就是讲解在OKHTTP中如何配置缓存。 HTTP协议中缓存相关 为了更好的讲解OKHTTP怎么设置缓存,我们追...

  • retrofit 缓存设置

    retrofit 缓存设置 CacheInterceport 配置okhttp及retrofit

  • OkHttp缓存配置

    前言 废话不多说,先奉上OkHttp GitHub 说到OKHTTP,我想你肯定不会陌生,Android中无数大大...

  • CacheInterceptor源码分析

    开头 首先我们回忆下在Okhttp中如何使用缓存: 可以发现首先需要配置缓存目录,缓存大小,然后就按照正常的方法请...

  • OkHttp源码探究

    OkHttp版本:3.11.0 对其常用使用过程进行分析: OkHttp的缓存参考下篇文章:OkHttp的缓存 -...

  • Retrofit和OkHttp使用网络缓存数据

    OkHttp缓存优化你的应用 Okhttp缓存原理 我们先从HTTP协议开始入手,关于缓存的HTTP请求/返回头由...

  • OKHTTP之缓存配置详解

    前言 在Android开发中我们经常要进行各种网络访问,比如查看各类新闻、查看各种图片。但有一种情形就是我们每次重...

  • okhttp 3.10缓存原理

    接主文okhttp 3.10详细介绍okhttp的缓存机制,缓存代码都在拦截器CacheInterceptor中实...

  • OkHttp高效开发介绍

    一.开启OKHttp缓存OKHTTP有自己的网络缓存机制,针对GET请求 有网时 获取数据并缓存,没网时会看是否有...

  • OkHttp讲解(三)

    OkHttp讲解(一)OkHttp讲解(二)OkHttp讲解(三) 一、HTTP缓存机制 1.1、分类 1 强制缓...

网友评论

  • 木子而东:大神,你好,你的拦截器中配置缓存有效时间,有网保存一天,无网络保存4周,为什么要设置这种策略啊,就一个策略(两三天不就行了),还有我想在有网的时候根据后台给出的是否是最新的(一个标志),在确定是从缓存取数据还是从服务端取数据,这种策略okhttp怎么写啊
  • Android砖家:你确定post请求也能这样缓存数据
    if (!requestMethod.equals("GET")) {
    // Don't cache non-GET responses. We're technically allowed to cache
    // HEAD requests and some POST requests, but the complexity of doing
    // so is high and the benefit is low.
    return null;
    }
    这是okhttp Cache类对缓存数据的说明,get请求有效。。。
    净叶不沉:在哪都能看到你的脚印。。。。作者说的是get请求并且服务器不配合的情况下的缓存方案,post缓存用数据库磁盘缓存,网上应该有很多方案
  • 宋木木的征途是星辰大海:请问如何去缓存post请求返回数据
  • 恨自己不能小清新:如果服务端支持缓存也需要写Interceptor吗? :flushed:
    恨自己不能小清新:@TrancyDeng 如果服务端支持缓存 我在okhttpclient配置一下cache 然后可以看到手机sd卡确实存在缓存 但是断网后,我还需要什么操作去读取缓存 做到离线缓存
    TrancyDeng:那个就不需要了,主要是看需求,如果你想客户端控制缓存时间的话就需要配置下
  • de89be2fcf9a:大神 你这代码运行后 会出现异常 无法解析我之前访问的地址
    de89be2fcf9a:@TrancyDeng 你这个写法是需要服务器配合的吧 不依赖服务器来处理缓存应该怎么做呢
    TrancyDeng:@刘婧琳 怎么个无法解析呢,我这是从项目里直接拷过来的
  • 云逸枫林:大神 我发现你了

本文标题:OkHttp缓存配置

本文链接:https://www.haomeiwen.com/subject/lrildttx.html