I am using Retrofit - OkHttp for web service call.
While using OkHttpClient.Builder of OkHttp to get OkHttpClient,
there is parameter for cache.
See below line:
OkHttpClient.Builder builder = new OkHttpClient.Builder()
.cache(?);// This last parameter
How to set this cache parameter ?
Using below code we can able to set Application level cache directory for OkHttpClient:
// Install an HTTP cache in the application cache directory.
File cacheDir = new File(app.getCacheDir(), "http");
// [app] is your Application class object.
// using [app.getCacheDir()], get app cache directory.
Cache cache = new Cache(cacheDir, DISK_CACHE_SIZE);
//DISK_CACHE_SIZE is constant for OkHttpClient cache directory size.
//private int DISK_CACHE_SIZE = 50 * 1024 * 1024; // 50MB
OkHttpClient.Builder builder = new OkHttpClient.Builder()
.cache(cache);
OkHttpClient okHttpClient=builder.build();
Related
I have a JSON API which is returning 6000+ objects in a JSONArray.
I've implemented Rxjava calling a retrofit GET API call. There isn't any error, but just a sentence stating "Do partial code cache collection, code=30KB, data=19KB".
How do I get the API data? Can I increase the cache for the retrofit response?
I am not sure configuring your cache size will solve your problem but you can increase cache by configuring your Client. If you are using OkHttpClient, you can do it something like this
val clientBuilder = OkHttpClient.Builder()
//pass context here
val cacheDir = File(context.applicationContext.cacheDir, "someChildName")
//Required Cache size
val DISK_CACHE_SIZE = 50 * 1024 * 1024; // 50MB
val cache = Cache(cacheDir, DISK_CACHE_SIZE)
//You can use .cache() to configure your Client
clientBuilder.cache(cache).build()
In your Manifest file you can set it like below, android:largeHeap="true":
<application
android:icon="#drawable/app_logo4"
android:label="#string/app_name"
android:largeHeap="true"
But a phone with limited RAM capacity or old phones will be slow.
If the API is providing pagination then better use pagination, because 6000+ data is huge. Your app's performance will degrade, and you will probably also receive an out of memory (OOM) exception and in low connection scenarios your app always receives a timeout issue.
One solution is you set your timeout in minutes .connectTimeout(15, TimeUnit.MINUTES);, use #Sagar Vekariya code. And don't call your API in the main thread; better use a coroutine.
fun methodName(callback:(ArrayList<Bean>)->Unit) {
GlobalScope.launch(Dispatchers.IO) {
val list = get6KData()
callback.invoke(list)
}
}
You can do one more thing. Don't convert a response in Objects; just take it as a simple JSON text file. That will solve your OOM issue. Later parse the JSON content and insert in the database directly and fire a query in the database and use pagination to list in the app. For example,
fun methodName() {
GlobalScope.launch(Dispatchers.IO) {
val json = get6KData() // Get JSON text here
parsingNinsertDB(json)
// Here you can return the first batch or use another common method for pagination
}
}
fun pageMethod(pageNo:Int,callback:(ArrayList<Bean>)->Unit) {
GlobalScope.launch(Dispatchers.IO) {
val list = db.get6KData(pageNo)
callback.invoke(list)
}
}
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder builder = new OkHttpClient().newBuilder();
builder.addInterceptor(logging);
builder.readTimeout(60, TimeUnit.SECONDS);
builder.connectTimeout(5, TimeUnit.MINUTES);
Gson gson = new GsonBuilder()
.setLenient()
.create();
OkHttpClient httpClient = builder.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.client(httpClient)
.build();
I'm using OKHTTP and Retrofit to handle network calls, I'm not sure how can I clear the cache when user logs out,I'm using MVP/Repository pattern and dagger on my Project
This is the sample project I'm referring
https://github.com/LadwaAditya/DaggerRetrofitOkhttp-Tutorial
OkHttpClient tempClient = new OkHttpClient.Builder()
.readTimeout(60, TimeUnit.SECONDS)// connect timeout
.connectTimeout(60, TimeUnit.SECONDS)// socket timeout
.followRedirects(false)
.cache(provideHttpCache())
.addNetworkInterceptor(new ResponseCacheInterceptor())
.addInterceptor(new AddHeaderAndCookieInterceptor())
.build();
private Cache provideHttpCache() {
Cache cache = new Cache(new File(Application.getAppInstance().getCacheDir(), CACHE_DIR_NAME), CACHE_SIZE);
return cache;
}
OKHTTP has a Cache.evict method but I'm not sure how expose this method
Have you tried referencing your Cache from your OkHttpClient on logout and calling tempClient.cache().delete()? Both delete() and evictAll() appear to be public from the documentation.
I need to implement basic caching of API responses. I've made a little playground project that calls GitHub API and caching was successful (I've used Charles to verify that). However when I transferred this solution to my target project caching didn't work anymore. Could multiple interceptors in the chain be the reason?
Code from playground project (working):
Interceptor (same for target project):
public class CacheControlInterceptor implements Interceptor {
#Override
public Response intercept(Chain chain) throws IOException {
Response response = chain.proceed(chain.request());
return response.newBuilder()
.header("Cache-Control", "only-if-cached")
.build();
}
}
Cache and client declaration:
long SIZE_OF_CACHE = 10 * 1024 * 1024; // 10 MB
final Cache cache = new Cache(new File(getCacheDir(), "retrofit_cache"), SIZE_OF_CACHE);
OkHttpClient.Builder client = new OkHttpClient.Builder().cache(cache);
client.networkInterceptors().add(new CacheControlInterceptor());
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/users/")
.addConverterFactory(GsonConverterFactory.create())
.client(client.build())
.build();
Screen from debugging of CacheControlInterceptor:
screen
Code from target project (NOT working):
Cache and client declaration:
private OkHttpClient provideOkHttpClient() {
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder okhttpClientBuilder = new OkHttpClient.Builder();
okhttpClientBuilder.connectTimeout(30, TimeUnit.SECONDS);
okhttpClientBuilder.readTimeout(30, TimeUnit.SECONDS);
okhttpClientBuilder.writeTimeout(30, TimeUnit.SECONDS);
okhttpClientBuilder.addInterceptor(loggingInterceptor);
okhttpClientBuilder.addInterceptor(new JwtRenewInterceptor(getUserSession()));
okhttpClientBuilder.addInterceptor(new AutoLoginInterceptor(getUserSession()));
okhttpClientBuilder.addNetworkInterceptor(new CacheControlInterceptor());
long SIZE_OF_CACHE = 10 * 1024 * 1024; // 10 MB
final Cache cache = new Cache(new File(getCacheDir(), "retrofit_cache"), SIZE_OF_CACHE);
okhttpClientBuilder.cache(cache);
return okhttpClientBuilder.build();
}
Screen from debugging of CacheControlInterceptor: screen
If you want apply some headers to all requests using OkHttp cache you should use Application interceptor, not network interceptor. Otherwise, you are not giving cache mechanism a chance to return cached responses.
It's nicely illustrated on OkHttp wiki
So most probably what is happening in your code is that you let Cache to store responses but you never use them since requests going to Cache are missing only-if-cached header.
Try
okhttpClientBuilder.addInterceptor(new CacheControlInterceptor());
Actually the mistake was caused by my poor reasoning about http headers. I thought that method addHeader or header will simply add key Cache-Control and then value only-if-cached. However it adds only value! And since in my target project's API there was no header key Cache-Control (unlike in GitHub API) there was no place for value only-if-cached to be stored.
Am using retrofit 1.9 during offline i need to make use of cache response from server so how to create cache response in retrofit i have heard i can be done with okhttp but can somebody share snippet sample how to make use of cache response?
I am setting cache response like is this right way?
int cacheSize = 10 * 1024 *1024;
File cacheDirectory = new File(mcontext.getCacheDir().getAbsolutePath(), "HttpCache");
Cache cache = new Cache(cacheDirectory, cacheSize);
OkHttpClient client1 = new OkHttpClient();
client1.setCache(cache);
RestAdapter adapter = new RestAdapter.Builder().setEndpoint(url).setClient(new OkClient(client1)).build();
RetrofitRest retro = adapter.create(RetrofitRest.class);
I am using below code to cache in Android device to collect the response and get from cache till the max age expires. When i use "public" I was able to see the response cached in my application installed folder(/data/data/app_folder).
I tried all below none of them works for "private" but when I change to "public" all my solutions i tried works.
But I need to make it to work for "private". Am I missing something.
Header I will receive "Cache-Control", "private,max-age=120"
Solution 1:
File httpCacheDirectory = new File(context.getCacheDir(), "responses");
HttpResponseCache httpResponseCache = null;
try {
httpResponseCache = new HttpResponseCache(httpCacheDirectory, 10 * 1024 * 1024);
} catch (IOException e) {
Log.e("Retrofit", "Could not create http cache", e);
}
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setResponseCache(httpResponseCache);
Solution 2:
And I am using Retrofit library, an Android client.
Cache cache = new Cache(cacheDirectory, cacheSize);
client = new OkHttpClient();
client.setCache(cache);