当前位置: 首页 > 面试题库 >

Java可以在脱机时使用OKHttp进行改造以使用缓存数据

柯苗宣
2023-03-14
问题内容

我正在尝试使用Retrofit&OKHttp来缓存HTTP响应。我遵循了这个要点,并最终获得了以下代码

File httpCacheDirectory = new File(context.getCacheDir(), "responses");

HttpResponseCache httpResponseCache = null;
try {
     httpResponseCache = new HttpResponseCache(httpCacheDirectory, 10 * 1024 * 1024);
} catch (IOException e) {
     Log.e("Retrofit", "Could not create http cache", e);
}

OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setResponseCache(httpResponseCache);

api = new RestAdapter.Builder()
          .setEndpoint(API_URL)
          .setLogLevel(RestAdapter.LogLevel.FULL)
          .setClient(new OkClient(okHttpClient))
          .build()
          .create(MyApi.class);

这是MyApi,带有Cache-Control标头

public interface MyApi {
   @Headers("Cache-Control: public, max-age=640000, s-maxage=640000 , max-stale=2419200")
   @GET("/api/v1/person/1/")
   void requestPerson(
           Callback<Person> callback
   );

首先,我在线请求并检查缓存文件。正确的JSON响应和标头在那里。但是,当我尝试离线请求时,我总是得到RetrofitError UnknownHostException。我还需要做些其他事情来使Retrofit从缓存中读取响应吗?

编辑: 由于OKHttp 2.0.x HttpResponseCacheCache,setResponseCachesetCache


问题答案:

编辑改造2.x:

OkHttp Interceptor是脱机时访问缓存的正确方法:

1)创建拦截器:

private static final Interceptor REWRITE_CACHE_CONTROL_INTERCEPTOR = new Interceptor() {
    @Override public Response intercept(Chain chain) throws IOException {
        Response originalResponse = chain.proceed(chain.request());
        if (Utils.isNetworkAvailable(context)) {
            int maxAge = 60; // read from cache for 1 minute
            return originalResponse.newBuilder()
                    .header("Cache-Control", "public, max-age=" + maxAge)
                    .build();
        } else {
            int maxStale = 60 * 60 * 24 * 28; // tolerate 4-weeks stale
            return originalResponse.newBuilder()
                    .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
                    .build();
        }
    }

2)安装客户端:

OkHttpClient client = new OkHttpClient();
client.networkInterceptors().add(REWRITE_CACHE_CONTROL_INTERCEPTOR);

//setup cache
File httpCacheDirectory = new File(context.getCacheDir(), "responses");
int cacheSize = 10 * 1024 * 1024; // 10 MiB
Cache cache = new Cache(httpCacheDirectory, cacheSize);

//add cache to the client
client.setCache(cache);

3)将客户添加到改造中

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl(BASE_URL)
        .client(client)
        .addConverterFactory(GsonConverterFactory.create())
        .build();

另请检查@kosiara-Bartosz Kosarzycki的答案。您可能需要从响应中删除一些标头。

OKHttp 2.0.x(检查原始答案):
由于OKHttp 2.0.x HttpResponseCache是Cache,所以setResponseCache是setCache。因此,您应该setCache这样:

        File httpCacheDirectory = new File(context.getCacheDir(), "responses");

        Cache cache = null;
        try {
            cache = new Cache(httpCacheDirectory, 10 * 1024 * 1024);
        } catch (IOException e) {
            Log.e("OKHttp", "Could not create http cache", e);
        }

        OkHttpClient okHttpClient = new OkHttpClient();
        if (cache != null) {
            okHttpClient.setCache(cache);
        }
        String hostURL = context.getString(R.string.host_url);

        api = new RestAdapter.Builder()
                .setEndpoint(hostURL)
                .setClient(new OkClient(okHttpClient))
                .setRequestInterceptor(/*rest of the answer here */)
                .build()
                .create(MyApi.class);


 类似资料:
  • 问题内容: 我已经在中解析了JSON数据,现在想使其脱机使用。有没有一种方法可以将JSON数据保存在电话上,以便在电话离线时可以查看数据? 有人知道一个例子吗? 编辑现在可以使用: 问题答案: 您有两种方法。您可以创建一个数据库,然后将所有数据保存在那里,并在需要时将其取回。或者,如果您拥有的数据不是很多,并且您不想处理数据库,那么您可以将json字符串写入存储卡中的文本文件,并在离线时稍后阅读。

  • 我正在尝试运行一个具有许多依赖项的Java应用程序。在过去,我使用以下命令启动应用程序 然而,随着依赖项列表的增加,我将它们移到了一个参数文件中,该文件的内容包括: 我正在用 到目前为止,一切正常。 有时我最终会得到测试版的程序。jar,它们共享所有相同的依赖项,但程序不同。jar被重命名为程序测试版。jar。 因此,要运行jar,将使用以下命令 或者更具体地说,我将使用一个环境变量,以便可以使用

  • 我有一个简单的用例,服务器为请求返回Etag,并将该Etag作为标头(即)添加到所有后续url请求。如果响应中有变化,服务器可以用响应,否则可以用响应。对于后者,重用缓存中的响应是有意义的。但是okhttp总是返回作为缓存响应。 我做了一些故障排除,okhttp在内部将响应写入磁盘,但是不会将其返回到。仔细研究类,有一些文档明确说明不会使用缓存: 编辑-更正,Okhttp正确地添加了etag标头。

  • 我希望有人能对我一直在研究但没有取得多大进展的一些事情有所帮助。 我想利用 NSURLCache 来返回我在 iOS 应用程序中进行的 API 调用的缓存响应。当设备联机时,如果缓存的响应足够新,我想返回它,否则从远程获取。当设备脱机时,我希望立即返回缓存的响应(如果有),无论其年龄如何。 我正在使用AFNetworking。我正在对我控制的服务器进行API调用。协议是HTTPS。响应头当前为。我

  • 本文向大家介绍Dubbo可以对结果进行缓存吗?相关面试题,主要包含被问及Dubbo可以对结果进行缓存吗?时的应答技巧和注意事项,需要的朋友参考一下 可以,Dubbo 提供了声明式缓存,用于加速热门数据的访问速度,以减少用户加缓存的工作量。