原文地址:https://medium.com/mindorks/caching-with-retrofit-store-responses-offline-71439ed32fda
当你使用Retrofit的时候,构建Retrofit实例:
val retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
上面的实例使用的是默认的OkHttpClient作为客户端来执行请求。但是缓存不友好。
接下来我们将创建一个启用缓存的OkHttpClient实例,并且可以处理有效的数据获取。
创建缓存友好的OkHttpClient
- 定义一个方法用来检查网络连接情况
fun hasNetwork(context: Context): Boolean? {
var isConnected: Boolean? = false
var connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val activeNetwork: NetworkInfo? = connectivityManager.activeNetworkInfo
if(activeNetwork != null && activeNetwork.isConnected)
isConnectd = true
return isConnected
}
- 定义缓存大小
val cacheSize = (5 * 1024 * 1024).toLong()
- 创建缓存变量
val myCache = Cache(context.cacheDir, cacheSize)
- 使用拦截器创建OkHttpClient实例
val okHttpClient = OkHttpClient.Builder()
// Specify the cache we created earlier.
.cache(myCache)
// Add an Interceptor to the OkHttpClient.
.addInterceptor { chain ->
// Get the request from the chain.
var request = chain.request()
/*
* Leveraging the advantage of using Kotlin,
* we initialize the request and change its header depending on whether
* the device is connected to Internet or not.
*/
request = if (hasNetwork(context)!!)
/*
* If there is Internet, get the cache that was stored 5 seconds ago.
* If the cache is older than 5 seconds, then discard it,
* and indicate an error in fetching the response.
* The 'max-age' attribute is responsible for this behavior.
*/
request.newBuilder().header("Cache-Control", "public, max-age=" + 5).build()
else
/*
* If there is no Internet, get the cache that was stored 7 days ago.
* If the cache is older than 7 days, then discard it,
* and indicate an error in fetching the response.
* The 'max-stale' attribute is responsible for this behavior.
* The 'only-if-cached' attribute indicates to not retrieve new data; fetch the cache only instead.
*/
request.newBuilder().header("Cache-Control", "public, only-if-cached, max-stale=" + 60 * 60 * 24 * 7).build()
// End of if-else statement
// Add the modified request to the chain.
chain.proceed(request)
}
.build()
将他们都结合到一起
val retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
// Adding our OkHttpClient
.client(okHttpClient)
.build()
下面就是最终的代码:
val cacheSize = (5 x 1024 x 1024).toLong()
val myCache = Cache(context.cacheDir, cacheSize)
val okHttpClient = OkHttpClient.Builder()
.cache(myCache)
.addInterceptor { chain ->
var request = chain.request()
request = if (hasNetwork(context)!!)
request.newBuilder().header("Cache-Control", "public, max-age=" + 5).build()
else
request.newBuilder().header("Cache-Control", "public, only-if-cached, max-stale=" + 60 * 60 * 24 * 7).build()
chain.proceed(request)
}
.build()
val retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(okHttpClient)
.build()
网友评论