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

改造-Okhttp客户端如何缓存响应

金晨
2023-03-14
问题内容

我正在尝试通过OkHttp(2.3.0)缓存Retrofit(v
1.9.0)完成的http调用的响应。如果我尝试在没有互联网的情况下拨打电话,它总是打网络电话java.net.UnknownHostException

RestClient

public class RestClient {
public static final String BASE_URL = "http://something.example.net/JSONService";
private com.ucc.application.rest.ApiService apiService;

public RestClient() {
    Gson gson = new GsonBuilder()
            .setDateFormat("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'SSS'Z'")
            .create();

    RequestInterceptor requestInterceptor = new RequestInterceptor() {

        @Override
        public void intercept(RequestFacade request) {
            request.addHeader("Accept", "application/json");
            int maxAge = 60 * 60;
            request.addHeader("Cache-Control", "public, max-age=" + maxAge);
        }
    };

    RestAdapter restAdapter = new RestAdapter.Builder()
            .setLogLevel(RestAdapter.LogLevel.FULL)
            .setEndpoint(BASE_URL)
            .setClient(new OkClient(OkHttpSingleTonClass.getOkHttpClient()))
            .setConverter(new GsonConverter(gson))
            .setRequestInterceptor(requestInterceptor)
            .build();

    apiService = restAdapter.create(com.ucc.application.rest.ApiService.class);
}

public com.ucc.application.rest.ApiService getApiService() {
    return apiService;
}

}

OkHttpSingleTonClass

public class OkHttpSingleTonClass {


private static OkHttpClient okHttpClient;

private OkHttpSingleTonClass() {
}

public static OkHttpClient getOkHttpClient() {
    if (okHttpClient == null) {
        okHttpClient = new OkHttpClient();
        createCacheForOkHTTP();
    }
    return okHttpClient;
}

private static void createCacheForOkHTTP() {
    Cache cache = null;
    cache = new Cache(getDirectory(), 1024 * 1024 * 10);
    okHttpClient.setCache(cache);
}

public static File getDirectory() {
    final File root = new File(Environment.getExternalStorageDirectory() + File.separator + "UCC" + File.separator);
    root.mkdirs();
    final String fname = UserUtil.CACHE_FILE_NAME;
    final File sdImageMainDirectory = new File(root, fname);
    return sdImageMainDirectory;
}

}

我的活动

Request request = new Request.Builder()
            .cacheControl(new CacheControl.Builder()
                    .onlyIfCached()
                    .maxAge(60 * 60, TimeUnit.SECONDS)
                    .build())
            .url(RestClient.BASE_URL + Constants.GET_ABOUT_US_COLLECTION + "?userid=59e41b02-35ed-4962-8517-2668b5e8dae3&languageid=488d8f13-ef7d-4a3a-9516-0e0d24cbc720")
            .build();
    Log.d("url_request", RestClient.BASE_URL + Constants.GET_ABOUT_US_COLLECTION + "/?userid=10");
    com.squareup.okhttp.Response forceCacheResponse = null;
    try {
        forceCacheResponse = OkHttpSingleTonClass.getOkHttpClient().newCall(request).execute();
    } catch (IOException e) {
        e.printStackTrace();
    }
    if (forceCacheResponse.code() != 504) {
        // The resource was cached! Show it.
        Log.d("From", "Local");
        Toast.makeText(AboutUs.this, "Local", Toast.LENGTH_SHORT).show();
    } else {
        // The resource was not cached.
        Log.d("From", "Network");
        Toast.makeText(AboutUs.this, "Network", Toast.LENGTH_SHORT).show();
        getAbouUsDetails();//This will use the Apiservice interface to hit the server.

    }

我遵循了这一点。但是我无法工作。它只是从服务器上命中。我究竟做错了什么?


问题答案:

根据1.9.0使用的OkClient翻新版不支持html" target="_blank">缓存。我们必须使用OkHttpClientSquare OkHttpClient库的实例。

你可以通过编译 compile 'com.squareup.okhttp:okhttp:2.3.0'

在一切翻新之前,都通过响应标头来缓存

Cache-Control:max-age=120,only-if-cached,max-stale

** 120是秒。

您可以在此处阅读有关标题的更多信息。

缓存头通常由服务器响应指示。 尝试在服务器中实现缓存头。 如果您没有选择,可以进行改装。

private static final Interceptor REWRITE_CACHE_CONTROL_INTERCEPTOR = new Interceptor() {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Response originalResponse = chain.proceed(chain.request());
        return originalResponse.newBuilder()
                .header("Cache-Control", String.format("max-age=%d, only-if-cached, max-stale=%d", 120, 0))
                .build();
    }
};

缓存位置:

private static void createCacheForOkHTTP() {
    Cache cache = null;
    cache = new Cache(getDirectory(), 1024 * 1024 * 10);
    okHttpClient.setCache(cache);
}

// returns the file to store cached details
private File getDirectory() {
    return new File(“location”);
}

将拦截器添加到OkHttpClient实例:

okHttpClient.networkInterceptors().add(REWRITE_CACHE_CONTROL_INTERCEPTOR);

最后将OkHttpClient添加到RestAdapter中:

RestAdapter.setClient(new OkClient(okHttpClient));

您可以浏览此幻灯片以获取更多参考。



 类似资料:
  • 问题内容: 我正在使用OkHttp客户端和Jackson的Retrofit进行Json序列化,并想获取响应的标头。 我知道我可以扩展OkClient并拦截它。但这是在反序列化过程开始之前进行的。 我基本上需要的是将标头与反序列化的Json Object一起使用。 问题答案: 在Retrofit 1.9.0中,如果您使用接口的回调异步版本, 然后您的回调将收到一个对象 其中有一个方法叫做 对于Ret

  • 我想知道如何缓存来自Web服务器(返回json数据)的okHTTP响应? 你知道如果应用程序只需要在第一次运行时下载数据--然后只有在数据发生变化时才下载数据该怎么办吗?

  • 我想知道以下问题的答案: 1)如果Ignite服务器重新启动,我需要重新启动客户端(web应用程序)。是否有任何方法可以在服务器重新启动时重新连接到服务器。我知道当服务器重新启动时,它分配了一个不同的ID,因此当前现有的连接变得过时。是否有方法克服这个问题,如果是的话,哪一个版本的Ignite支持这个功能。目前我使用1.7版本 3)如果我有一个大对象要缓存,我发现序列化和反序列化在Ignite中需

  • 问题内容: 我们有一个gwt-client,它从我们的服务器接收很多数据。从逻辑上讲,我想在客户端缓存数据,以免服务器收到不必要的请求。 截止到今天,我已经让我的模型来处理数据缓存,但伸缩性不是很好。这也成为一个问题,因为我们团队中的不同开发人员都开发了自己的“缓存”功能,从而使项目充满重复性。 我正在考虑如何实现一个“单入口”来处理所有缓存,而使模型对如何处理缓存一无所知。 有没有人在GWT中进

  • 我需要一些帮助来理解为什么在Eureka注册的服务会想要彼此通信,尽管没有实际运行。例如,我在尤里卡注册了服务A和服务B。如果我搞垮了服务B,那么即使服务A没有运行,它仍然会尝试与服务B进行30秒到3分钟的通信。这样做的目的是什么?有什么办法可以绕过它吗?谢谢你!

  • 我在OkHttp客户端和Jackson上使用reform进行Json序列化,并希望获得响应的头。 我知道我可以扩展OkClient并拦截它。但这发生在反序列化过程开始之前。 我基本上需要的是获取头文件和反序列化的Json对象。