Men*_*ena 4 android caching retrofit retrofit2 okhttp3
我阅读了几十个教程和Stackoverflow对我的问题的答案,但没有什么对我有用!此外,他们中的大多数都是旧的,所以OKHTTP可能会以某种方式改变.
我想要的只是为Retrofit 启用离线缓存.
我正在使用GET
我曾尝试仅用offlineCacheInterceptor作拦截器,但我一直得到:
Unable to resolve host "jsonplaceholder.typicode.com": No address associated with hostname
Run Code Online (Sandbox Code Playgroud)
我尝试使用offlineCacheInterceptorInterceptor + provideCacheInterceptor()作为NetworkInterceptor的组合,但我一直得到:
504 Unsatisfiable Request (only-if-cached) and a null response.body()
Run Code Online (Sandbox Code Playgroud)
我甚至确保.removeHeader("Pragma")到处添加!
我尝试了所有这些链接:
https://newfivefour.com/android-retrofit2-okhttp3-cache-network-request-offline.html (一个拦截器,不工作!!)
https://medium.com/mindorks/caching-with-retrofit-store-responses-offline-71439ed32fda(一个拦截器,不工作!)
https://caster.io/lessons/retrofit-2-offline-cache(单独在线+离线缓存,不工作)
https://www.journaldev.com/23297/android-retrofit-okhttp-offline-caching(不工作,504不满意请求(仅限缓存))
http://mikescamell.com/gotcha-when-offline-caching-with-okhttp3/(一个拦截器,不工作!!)
/sf/answers/3380677821/(不工作)无法解析主机"jsonplaceholder.typicode.com":没有与主机名关联的地址
使用OKHttp进行改造可以在离线时使用缓存数据 (令人困惑!)
这是我的代码:
public static Retrofit getRetrofitInstance(Context context) {
if (retrofit == null) {
c = context;
int cacheSize = 10 * 1024 * 1024; // 10 MB
Cache cache = new Cache(context.getCacheDir(), cacheSize);
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor(provideHttpLoggingInterceptor())
.addInterceptor(offlineCacheInterceptor)
.addNetworkInterceptor(provideCacheInterceptor())
.cache(cache)
.build();
//////////////////////////
retrofit = new retrofit2.Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(okHttpClient)
.build();
}
return retrofit;
}
Run Code Online (Sandbox Code Playgroud)
public static Interceptor offlineCacheInterceptor = new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Log.e("bbbb", "bbbb");
if (!checkInternetAvailability()) {
Log.e("aaaaa", "aaaaaa");
CacheControl cacheControl = new CacheControl.Builder()
.maxStale(30, TimeUnit.DAYS)
.build();
request = request.newBuilder()
.cacheControl(cacheControl)
.removeHeader("Pragma")
.build();
}
return chain.proceed(request);
}
};
Run Code Online (Sandbox Code Playgroud)
public static Interceptor provideCacheInterceptor() {
return new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Response response = chain.proceed(chain.request());
// re-write response header to force use of cache
CacheControl cacheControl = new CacheControl.Builder()
.maxAge(2, TimeUnit.MINUTES)
.build();
return response.newBuilder()
.header(CACHE_CONTROL, cacheControl.toString())
.removeHeader("Pragma")
.build();
}
};
}
Run Code Online (Sandbox Code Playgroud)
我正在使用jsonplaceholder.typicode.com/photos返回:
content-type: application/json; charset=utf-8
date: Sun, 21 Oct 2018 14:26:41 GMT
set-cookie: __cfduid=d9e935012d2f789245b1e2599a41e47511540132001; expires=Mon, 21-Oct-19 14:26:41 GMT; path=/; domain=.typicode.com; HttpOnly
x-powered-by: Express
vary: Origin, Accept-Encoding
access-control-allow-credentials: true
expires: Sun, 21 Oct 2018 18:26:41 GMT
x-content-type-options: nosniff
etag: W/"105970-HCYFejK2YCxztz8++2rHnutkPOQ"
via: 1.1 vegur
cf-cache-status: REVALIDATED
expect-ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
server: cloudflare
cf-ray: 46d466910cab3d77-MXP
Cache-Control: public, max-age=60
Run Code Online (Sandbox Code Playgroud)
Men*_*ena 22
好吧,所以使用OKHTTP或Retrofit的在线和离线缓存已经在stackoverflow和其他论坛上给很多人带来了很多问题.互联网上有大量误导性信息和非工作代码样本.
那么,今天我将解释如何使用Retrofit和OKHTTP实现在线和离线缓存,并执行明确的步骤+如何测试并了解您是从缓存还是网络获取数据.
如果您正在获得504 Unsatisfiable Request (only-if-cached)OR,Unable to resolve host "HOST": No address associated with hostname那么您可以使用以下任何解决方案.
在开始之前,您必须始终记住:
.removeHeader("Pragma")如下所示(这使您可以覆盖服务器的缓存协议)注意:如果您想依赖服务器的缓存协议进行在线和离线缓存,请不要阅读2个解决方案.刚看完这篇文章.您所需要的只是创建一个缓存对象并将其附加到OKHTTPClient对象.
解决方案1 :(更长,但你有完全控制权)
第1步:(创建onlineInterceptor)
static Interceptor onlineInterceptor = new Interceptor() {
@Override
public okhttp3.Response intercept(Chain chain) throws IOException {
okhttp3.Response response = chain.proceed(chain.request());
int maxAge = 60; // read from cache for 60 seconds even if there is internet connection
return response.newBuilder()
.header("Cache-Control", "public, max-age=" + maxAge)
.removeHeader("Pragma")
.build();
}
};
Run Code Online (Sandbox Code Playgroud)第2步:(创建脱机拦截器)(仅当您希望脱机时访问缓存)
static Interceptor offlineInterceptor= new Interceptor() {
@Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request();
if (!isInternetAvailable()) {
int maxStale = 60 * 60 * 24 * 30; // Offline cache available for 30 days
request = request.newBuilder()
.header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
.removeHeader("Pragma")
.build();
}
return chain.proceed(request);
}
};
Run Code Online (Sandbox Code Playgroud)第3步:(创建缓存对象)
int cacheSize = 10 * 1024 * 1024; // 10 MB
Cache cache = new Cache(context.getCacheDir(), cacheSize);
Run Code Online (Sandbox Code Playgroud)第4步:(添加拦截器和缓存到OKHTTPClient对象)
OkHttpClient okHttpClient = new OkHttpClient.Builder()
// .addInterceptor(provideHttpLoggingInterceptor()) // For HTTP request & Response data logging
.addInterceptor(OFFLINE_INTERCEPTOR)
.addNetworkInterceptor(ONLINE_INTERCEPTOR)
.cache(cache)
.build();
Run Code Online (Sandbox Code Playgroud)第5步:(如果您使用的是Retrofit,请将OKHTTPClient对象添加到其中)
retrofit = new retrofit2.Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(okHttpClient)
.build();
Run Code Online (Sandbox Code Playgroud)DONE!
解决方案2 :(只需使用库为您完成所有这些!但处理限制)
第2步(创建一个OKHTTPClient对象)
OkHttpClient okHttpClient = OkCacheControl.on(new OkHttpClient.Builder())
.overrideServerCachePolicy(1, MINUTES)
.forceCacheWhenOffline(networkMonitor)
.apply() // return to the OkHttpClient.Builder instance
//.addInterceptor(provideHttpLoggingInterceptor())
.cache(cache)
.build();
Run Code Online (Sandbox Code Playgroud)第3步:(将OKHTTPClient对象附加到Retrofit,如上所示)
第4步:(创建NetworkMonitor对象)
static OkCacheControl.NetworkMonitor networkMonitor=new
OkCacheControl.NetworkMonitor() {
@Override
public boolean isOnline() {
return isInternetAvailable();
}
};
Run Code Online (Sandbox Code Playgroud)DONE!
测试:
为了了解您的设备是从网络还是从缓存获取数据,只需将以下代码添加到您onResponse的Retrofit方法中.
public void onResponse(Call<List<RetroPhoto>> call, Response<List<RetroPhoto>> response) {
if (response.raw().cacheResponse() != null) {
Log.e("Network", "response came from cache");
}
if (response.raw().networkResponse() != null) {
Log.e("Network", "response came from server");
}
}
Run Code Online (Sandbox Code Playgroud)
如果设备正在使用网络,您将收到"来自服务器的响应".
如果设备使用缓存,您将获得以上两种响应!有关此内容的更多信息,请阅读本文.
有关使用OKHTTP拦截器的更多信息,请转到此页面.
| 归档时间: |
|
| 查看次数: |
2160 次 |
| 最近记录: |