Caching response data using retrofit2 + okhttp3

I am using retrofit_2 (beta4) with okhttp_3 libraries in network requests. And I need to cache response data for situations when the network is disconnected, and the application should display the response data from the last identical request. All the manuals for solving this problem that I found were with okhttp lib (and not okhttp_3). I tried to solve the problem:

public class ApiFactory  {

private static final int CONNECT_TIMEOUT = 45;
private static final int WRITE_TIMEOUT = 45;
private static final int READ_TIMEOUT = 45;
private static final long CACHE_SIZE = 10 * 1024 * 1024; // 10 MB

private static OkHttpClient.Builder clientBuilder;
static {
    clientBuilder = new OkHttpClient
            .Builder()
            .connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS)
            .readTimeout(READ_TIMEOUT, TimeUnit.SECONDS)
            .writeTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS)
            .cache(new Cache(MyApp.getInstance().getCacheDir(), CACHE_SIZE)) // 10 MB
            .addInterceptor(new Interceptor() {
                @Override
                public Response intercept(Chain chain) throws IOException {
                    Request request = chain.request();
                    if (MyApp.getInstance().isNetwConn()) {
                        request = request.newBuilder().header("Cache-Control", "public, max-age=" + 60).build();
                    } else {
                        request = request.newBuilder().header("Cache-Control", "public, only-if-cached, max-stale=" + 60 * 60 * 24 * 7).build();
                    }
                    return chain.proceed(request);
                }
            });
}

@NonNull
public static ApiRequestService getApiRequestService() {
    return getRetrofitDefault().create(ApiRequestService.class);
}

@NonNull
private static Retrofit getRetrofitDefault() {
    return new Retrofit.Builder()
            .baseUrl(NetworkUrls.URL_MAIN)
            .addConverterFactory(GsonConverterFactory.create())
            .callbackExecutor(Executors.newFixedThreadPool(5))
            .callbackExecutor(Executors.newCachedThreadPool())
            .callbackExecutor(new Executor() {
                private final Handler mHandler = new Handler(Looper.getMainLooper());

                @Override
                public void execute(Runnable command) {
                    mHandler.post(command);
                }
            })
            .client(clientBuilder.build())
            .build();
}
}

but it does not work. All requests work well when the network is turned on, but does not return cache data when the network is turned off. Please help solve this problem.

+4
source share
3 answers

use

File cacheDir = new File(MyApplication.getContext().getCacheDir(), cache);
        myCache= new Cache(cacheDir, cacheSize);

        okHttpClient = new OkHttpClient();
        okHttpClient.setCache(myCache);
+1
source

, reset .

okhttp3.Response originalResponse = chain.proceed(request);
if (NetUtils.hasNetwork(mContext)) {
    //when the network is available, you use the '@Headers' cache time in the interface
    String cacheControl = request.cacheControl().toString();
    int maxAge = 60; // read from cache for 1 minute
    return originalResponse.newBuilder()
            .header("Cache-Control", cacheControl)
            //.header("Cache-Control", "public, max-age=" + maxAge)
            .removeHeader("Progma")
            .build();
} else {
    return originalResponse.newBuilder()
            .header("Cache-Control", "public, only-if-cached, max-stale=2419200") //60 * 60 * 24 * 28 4weeks
            .removeHeader("Pragma")
            .build();
}
0

Builder

OkHttpClient client = new OkHttpClient.Builder()
                .cache(cache).build();
0

All Articles