Here is my code where i am calling api and also define cache for okhttp with retrofit:
public class DemoPresenter {
DemoView vDemoView;
private Context mContext;
public DemoPresenter(Context mcontext, DemoView vDemoView) {
this.vDemoView = vDemoView;
this.mContext = mcontext;
}
public void callAllProduct() {
if (vDemoView != null) {
vDemoView.showProductProgressBar();
}
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.cache(new Cache(mContext.getCacheDir(), 10 * 1024 * 1024)) // 10 MB
.addInterceptor(new Interceptor() {
@Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request();
if (BasicUtility.isInternet(mContext)) {
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);
}
})
.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("www.xyz.com/data/")
.addConverterFactory(GsonConverterFactory.create())
.client(okHttpClient)
.build();
AllApi productApiService = retrofit.create(AllApi.class);
Call<ProductData> call = productApiService.getProduct();
try {
call.enqueue(new Callback<ProductData>() {
@Override
public void onResponse(Call<ProductData> call, Response<ProductData> response) {
ArrayList<Product> alproducts = new ArrayList<>();
try {
alproducts = response.body().getProductData();
onSuccess(alproducts);
} catch (Exception e) {
}
}
@Override
public void onFailure(Call<ProductData> call, Throwable t) {
}
});
} catch (Exception e) {
}
}
private void onSuccess(ArrayList<Product> alproducts) {
if (vDemoView != null) {
vDemoView.hideProductProgressBar();
vDemoView.onProductSuccess(alproducts);
}
}
}
Now from my main activity i am calling this presenter class:
DemoPresenter mDemoPresenter = new DemoPresenter(getApplicationContext(),this);
mDemoPresenter.callAllProduct();
Now when i run this activity with Internet connectivity then it works fine but when i disconnected internet and run this activity again then it wont load data from cache .
How can i load this data from cache if there is not internet ?
You need to add an offline Cache Interceptor for OkHttp to cache the response for offline use. You can also cache data for a minute and if the request is send within a minute, the data from the cache is used.
Follow this tutorial to understand more about caching data - https://krtkush.github.io/2016/06/01/caching-using-okhttp-part-1.html Also this Stack Overflow answer Can Retrofit with OKHttp use cache data when offline
Possible errors: Because you put everything inside
callAllProduct
(), so you each time create newokHttpClient
, and newCache
, you are not reusing your oldCache
. You functionally dependent on callAllProduct, callAllProduct depends on new okHttpClient, okHttpCient is functionality dependent on new cache. PuttingokHttpClient
outside yourcallAllProduct
() body makes you depend on the same old okHttpClient in each callAllProduct call. Just try this even though I also don't know how Retrofit internal caching works. If it still not working, I apologise for my not working idea, but I promise, I will help you again.The idea is: Each time you call callAllProduct(), you use okHttpClient request to Retrofit API layer. Retrofit layer checks if it already saved the data that is associated with your okHttpClient or not? Each new okHttpClient instance means each new http request, thus each new id it generates for the caching of data. Old cache is never used because each time you are using a new instance of okHttpClient. Retrofit doesn't see any associated id with your okHttpRequest instance, thus, forwards the request to internet. Web-server responses with data. Now, Retrofit creates new id for the cache for that successful ok HTTP client request. But when you use new okHttpClient each time, old cache id never used, thus there happens cache-miss always.
This below code should be outside
callAllProduct()
bodyNow, your callAllProduct() becomes as shown below:. This guarantees you use same okHttpClient all everytime you call callAllProduct().
Your interceptor should check for connectivity, and set cacheHeaderValue accordingly, In this example it uses a method isNetworkAvailable to do this:
You can try out this :
Working well for me.