Retrofit - Okhttp client How to cache the response

一曲冷凌霜 提交于 2019-11-26 22:34:49

问题


I'm trying to cache the response of http calls done by Retrofit(v 1.9.0) with OkHttp(2.3.0). It always made the network calls if I try to make a call without internet then 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;
}

}

MyActivity

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.

    } 

I followed this. But I can't manage to work. Its simply hitting from the server. What am i doing wrong?


回答1:


As per Retrofit 1.9.0 which uses OkClient does not have Caching support. We have to use OkHttpClient instance by Square OkHttpClient library.

You can compile by compile 'com.squareup.okhttp:okhttp:2.3.0'

Before everything retrofit caches by response headers like

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

** 120 is seconds.

You can read more about headers here.

Caching headers are mostly instructed by server response. Try to implement cache headers in servers. If you don't have an option, yes retrofit has it.

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();
    }
};

Where to cache:

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”);
}

Add interceptor to the OkHttpClient instance:

okHttpClient.networkInterceptors().add(REWRITE_CACHE_CONTROL_INTERCEPTOR);

And finally add OkHttpClient to the RestAdapter:

RestAdapter.setClient(new OkClient(okHttpClient));

And you can go through this slide for more reference.



来源:https://stackoverflow.com/questions/29119253/retrofit-okhttp-client-how-to-cache-the-response

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!