android - OkHttp3 cache seems to be unchecked with Retrofit 2 -
i'm trying setup http cache using retrofit (2.1.0) , okhttp (3.3.1). have seen many posts related topic, none of them helped.
i wrote unit tests see how cache works. works fine, once integrated in app, magic ends. first show implementation , explain of investigation.
first, here retrofit instantiation :
okhttpclient.builder httpbuilder = new okhttpclient.builder(); httplogginginterceptor logginginterceptor = new httplogginginterceptor(); interceptor.setlevel(httplogginginterceptor.level.headers); okhttpclient client = httpbuilder .addnetworkinterceptor(interceptor_response_set_cache) .addnetworkinterceptor(interceptor_request_add_checksum) .addinterceptor(logginginterceptor) .cache(cachehttpclient).build(); retrofit retrofit = new retrofit.builder() .addconverterfactory(gsonconverterfactory.create()) .client(client) .baseurl(base_url) .build();
here interceptor adding header set cache control:
private final interceptor interceptor_response_set_cache = new interceptor() { @override public response intercept(chain chain) throws ioexception { response response = chain.proceed(chain.request()); response = response.newbuilder() .header("cache-control", "max-age=600") //+ integer.tostring(3600 * 5) .build(); return response; } };
the last interceptor adds 2 url parameters:
private static final interceptor interceptor_request_add_checksum = new interceptor() { @override public response intercept(interceptor.chain chain) throws ioexception { httpurl url = chain.request().url(); url = url.newbuilder().addqueryparameter("rd", "random1").addqueryparameter("chk","check1").build(); request request = chain.request().newbuilder().url(url).build(); return chain.proceed(request); } };
finally, single method of service :
@headers("cache-control: public, max-stale=500") @get("/get_data") call<dataresponse> getdata(@query("year") int year, @query("month") int month, @query("day") int day);
about investigation, setup interceptor logger (app side, not network) see happening. can see lines such "cache-control: public, max-stale=500" in logs. means (at least me) header should give opportunity okhttp client check cache.
the cache seems correctly initialised. when create it, force initialisation , log urls present in cache. here how implemented:
file httpcachedirectory = new file(getcachedir(), "responses"); httpcachedirectory.getparentfile().mkdirs(); int cachesize = 10 * 1024 * 1024; // 10 mib cache cache = new cache(httpcachedirectory, cachesize); try { cache.initialize(); iterator<string> iterator = cache.urls(); log.i(tag, "urls in cachehttpclient : "); while (iterator.hasnext()) { log.i(tag, iterator.next()); } } catch (ioexception e) { e.printstacktrace(); log.i(tag, "cache not init"); }
when launch app wifi available, expected responses. kill app, disable wifi , relaunch app. expect cache serve data @ moment. fails , can see okhttp printed lines in logs :
http failed: java.net.unknownhostexception: unable resolve host "my-domain.com": no address associated hostname
last thing, in rfc 2616, 1 can read :
max-stale : indicates client willing accept response has exceeded expiration time. if max-stale assigned value, client willing accept response has exceeded expiration time no more specified number of seconds. if no value assigned max-stale, client willing accept stale response of age.
when don't specify value, works (i response when wifi down). way found make "work". maybe misunderstand cache-control directive !?
at point i'm confused. able use okhttp cache system, somehow i'm missing something.
thank reading text !
use method create cached okkhttpclient
private okhttpclient createcachedclient(final context context) { file httpcachedirectory = new file(context.getcachedir(), "cache_file"); cache cache = new cache(httpcachedirectory, 20 * 1024 * 1024); okhttpclient okhttpclient = new okhttpclient(); okhttpclient.setcache(cache); okhttpclient.interceptors().add( new interceptor() { @override public com.squareup.okhttp.response intercept(chain chain) throws ioexception { request originalrequest = chain.request(); string cacheheadervalue = isonline(context) ? "public, max-age=2419200" : "public, only-if-cached, max-stale=2419200" ; request request = originalrequest.newbuilder().build(); com.squareup.okhttp.response response = chain.proceed(request); return response.newbuilder() .removeheader("pragma") .removeheader("cache-control") .header("cache-control", cacheheadervalue) .build(); } } ); okhttpclient.networkinterceptors().add( new interceptor() { @override public com.squareup.okhttp.response intercept(chain chain) throws ioexception { request originalrequest = chain.request(); string cacheheadervalue = isonline(context) ? "public, max-age=2419200" : "public, only-if-cached, max-stale=2419200" ; request request = originalrequest.newbuilder().build(); com.squareup.okhttp.response response = chain.proceed(request); return response.newbuilder() .removeheader("pragma") .removeheader("cache-control") .header("cache-control", cacheheadervalue) .build(); } } ); return okhttpclient; } private boolean isonline(context context) { connectivitymanager connectivity = (connectivitymanager) _context.getsystemservice(context.connectivity_service); if (connectivity != null) { networkinfo[] info = connectivity.getallnetworkinfo(); if (info != null) (int = 0; < info.length; i++) if (info[i].getstate() == networkinfo.state.connected) { return true; } } return false; }
call createcachedclient() method create okhttpclient add client retrofit
okhttpclient okhttpclient = createcachedclient(mainactivity.this); retrofit retrofit=new retrofit.builder() .client(okhttpclient) .baseurl(api) .addconverterfactory(gsonconverterfactory .create()).build();
add permission manifest
<uses-permission android:name="android.permission.access_network_state"/>
if internet available first time call service , cache request,next time onwards upto 2419200 milliseconds use cache give response.it won't hit server upto 2419200 milliseconds if device if offline.
Comments
Post a Comment