OkHttp caching not working when there's internet or not
I'm trying to Make the application uses caching with Okhttp and Retrofit, so the problem that I have now is when I'm using **CacheInterceptor to cache the data**
it is getting the data from the internet, and When I'm using **ForceCacheInterceptor to get the data offline**
with it, it is not showing any data Whether there is Internet available or not. It is supposed to display Data if there is no Internet, but strange it is not displaying any Data whether there is an Internet or not when used.
So how can I fix this problem, Here's my code
My CacheInterceptor to cache the data
class CacheInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val response: Response = chain.proceed(chain.request())
lateinit var context: Context
return response.newBuilder()
.removeHeader("Pragma")
.removeHeader("Cache-Control")
.header(
"Cache-Control",
if (CheckNetwork.isInternetAvailable(context)) "public, max-age=60" else "public, only-if-cached, max-stale=604800"
) .build()
}
}
My ForceCacheInterceptor to get the data offline
class ForceCacheInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val builder: Request.Builder = chain.request().newBuilder()
lateinit var context: Context
if (!CheckNetwork.isInternetAvailable(context)) {
builder.cacheControl(CacheControl.FORCE_CACHE);
}
return chain.proceed(builder.build());
}
}
My NetworkLayer, Here I'm using OKhttp and retrofit
class NetworkLayer : AppCompatActivity() {
private val BASE_URL = ""
private val moshi: Moshi = Moshi.Builder().addLast(KotlinJsonAdapterFactory()).build()
private val myHttpClient = OkHttpClient()
override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
super.onCreate(savedInstanceState, persistentState)
val interceptor = HttpLoggingInterceptor()
interceptor.level = HttpLoggingInterceptor.Level.BODY
val httpCacheDirectory = File(applicationContext.cacheDir, "http-cache")
val cacheSize = 10 * 1024 * 1024 // 10 MiB
val cache = Cache(httpCacheDirectory, cacheSize.toLong())
myHttpClient
.newBuilder()
.addNetworkInterceptor(CacheInterceptor())
.addInterceptor(ForceCacheInterceptor())
.cache(cache)
.callTimeout(3, TimeUnit.SECONDS)
.connectTimeout(3, TimeUnit.SECONDS)
.build()
}
private val retrofit: Retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.client(myHttpClient)
.addConverterFactory(MoshiConverterFactory.create(moshi))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build()
val apiService: APIService by lazy {
retrofit.create(APIService::class.java)
}
}
And latest my check network class
object CheckNetwork {
private val TAG = CheckNetwork::class.java.simpleName
fun isInternetAvailable(context: Context): Boolean {
val info =
(context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager).activeNetworkInfo
return if (info == null) {
Log.d(TAG, "no internet connection")
false
} else {
if (info.isConnected) {
Log.d(TAG, " internet connection available...")
true
} else {
Log.d(TAG, " internet connection")
true
}
}
}
}
Solution 1:
As you said, the ForceCacheInterceptor
forces to use cache, even when an internet connection is available.
!CheckNetwork.isInternetAvailable(context)
will evalue to true
and force cache.
If no cache is available, then no data can be displayed, regardless of connectivity.
To resolve this issue, you have to cache data once, to be able to retrieve it when there's no internet connection.
Note: You cannot cache data, when no chace header is present:
(e.g. Cache-Control: public
or Cache-Control: max-age=3600
)
In case your response does not provide those headers, you have to add/modify them yourself.
Note: Doing so violates the decision by the author of the data and you should consider warning the user that the data is stale.