[英]Offline cache okhttp + retrofit not working
I am trying to activate a cache for offline browsing when no network is available. 我正在尝试在没有网络可用时激活缓存以进行离线浏览。 Unfortunatly it is somehow not working, when I debug the app, the interceptor nor cache is being accessed.
不幸的是,它在某种程度上不起作用,当我调试应用程序时,正在访问拦截器和缓存。
So I guess something is wrong with below code. 所以我想下面的代码有问题。
public class ApiHelper {
Context context;
private static final int TIMEOUT = 30;
private static final int WRITE_TIMEOUT = 30;
private static final int CONNECT_TIMEOUT = 10;
//private static final int CACHE_SIZE = 500 * 1024 * 1024;
private static final int CACHE_SIZE = 10 * 1024 * 1024;
public static final String baseUrl = "http://test.com/api-new/";
public ApiHelper(Context context) {
this.context = context;
}
private boolean isNetworkAvailable(Context context) {
ConnectivityManager connectivityManager
= (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}
// Configure access cache when offline
private final Interceptor REWRITE_CACHE_CONTROL_INTERCEPTOR = new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Response originalResponse = chain.proceed(chain.request());
if (isNetworkAvailable(context)) {
int maxAge = 60; // read from cache for 1 minute
return originalResponse.newBuilder()
.removeHeader("Pragma")
.header("Cache-Control", "public, max-age=" + maxAge)
.build();
} else {
int maxStale = 60 * 60 * 24 * 28; // tolerate 4-weeks stale
return originalResponse.newBuilder()
.removeHeader("Pragma")
.header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
.build();
}
}
};
private static OkHttpClient CLIENT = new OkHttpClient();
File httpCacheDirectory = new File(context.getCacheDir(), "HttpCache");
Cache cache = new Cache(httpCacheDirectory, CACHE_SIZE);
{
CLIENT = new OkHttpClient.Builder().
connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS).
writeTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS).
readTimeout(TIMEOUT, TimeUnit.SECONDS).
authenticator(new Authenticator()).
addInterceptor(REWRITE_CACHE_CONTROL_INTERCEPTOR).
cache(cache).
addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request;
UserModel user = HelperFactory.getDatabaseHelper().getUserDao().getCurrentUser();
if (user != null && user.getAccess_token() != null)
request = chain.request().newBuilder()
.addHeader("X-Auth-Token", user.getAccess_token()).build();
else
request = chain.request().newBuilder().build();
long t1 = System.nanoTime();
Logger.debug(ApiHelper.class.getName(), String.format("Sending request %s on %s%n",
request.url(), chain.connection()));
UserModel currentUser = HelperFactory.getDatabaseHelper().getUserDao().getCurrentUser();
if (currentUser != null)
Logger.debug(ApiHelper.class.getName(), "Sending request header " + request.headers().toString());
if (request != null && request.body() != null && request.body().contentLength() > 0) {
Buffer buffer = new Buffer();
request.body().writeTo(buffer);
String body = buffer.readUtf8();
Logger.debug(ApiHelper.class.getName(), "Sending request body " + body);
}
Response response = chain.proceed(request);
String msg = response.body().string();
long t2 = System.nanoTime();
Logger.debug(ApiHelper.class.getName(), String.format("Received response %s in %.1fms%nResponse code:%s%nReceived data: %s",
response.request().url(), (t2 - t1) / 1e6d, response.code(), msg));
return response.newBuilder()
.body(ResponseBody.create(response.body().contentType(), msg))
.headers(response.headers())
.build();
}
}).build();
}
@NonNull
public static MyApplication getInstance() {
Retrofit rf = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create(new GsonBuilder()
.excludeFieldsWithModifiers(Modifier.FINAL, Modifier.TRANSIENT, Modifier.STATIC)
.create()))
.client(CLIENT)
.build();
return rf.create(MyApplication.class);
}
}
You initialization block is non-static, but you never allocate an instance of this object, so it never gets run. 初始化块是非静态的,但是您永远不会分配此对象的实例,因此它永远不会运行。 It looks like you intended that to initialize the static member
CLIENT
. 看起来您打算初始化静态成员
CLIENT
。 Because this initialization ultimately depends on a Context
you can't convert that to a static initialization block. 因为此初始化最终取决于
Context
,所以无法将其转换为静态初始化块。 Convert it to an initialization method that takes a Context
parameter. 将其转换为采用
Context
参数的初始化方法。 Note: I also moved cache
and httpCacheDir
into this method as local variables. 注意:我还将
cache
和httpCacheDir
作为局部变量移动到此方法中。
private static boolean isNetworkAvailable(Context context) {
ConnectivityManager connectivityManager
= (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}
// Configure access cache when offline
private static Interceptor getInterceptor(Context context) {
return new Interceptor() {
@Override
//....
}
}
private static void initClient(Context context) {
httpCacheDirectory = File(context.getCacheDir(), "HttpCache");
Cache cache = new Cache(httpCacheDirectory, CACHE_SIZE);
CLIENT = new OkHttpClient.Builder().
connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS).
writeTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS).
readTimeout(TIMEOUT, TimeUnit.SECONDS).
authenticator(new Authenticator()).
addInterceptor(getInterceptor((context)).
cache(cache).
addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request;
UserModel user = HelperFactory.getDatabaseHelper().getUserDao().getCurrentUser();
if (user != null && user.getAccess_token() != null)
request = chain.request().newBuilder()
.addHeader("X-Auth-Token", user.getAccess_token()).build();
else
request = chain.request().newBuilder().build();
long t1 = System.nanoTime();
Logger.debug(ApiHelper.class.getName(), String.format("Sending request %s on %s%n",
request.url(), chain.connection()));
UserModel currentUser = HelperFactory.getDatabaseHelper().getUserDao().getCurrentUser();
if (currentUser != null)
Logger.debug(ApiHelper.class.getName(), "Sending request header " + request.headers().toString());
if (request != null && request.body() != null && request.body().contentLength() > 0) {
Buffer buffer = new Buffer();
request.body().writeTo(buffer);
String body = buffer.readUtf8();
Logger.debug(ApiHelper.class.getName(), "Sending request body " + body);
}
Response response = chain.proceed(request);
String msg = response.body().string();
long t2 = System.nanoTime();
Logger.debug(ApiHelper.class.getName(), String.format("Received response %s in %.1fms%nResponse code:%s%nReceived data: %s",
response.request().url(), (t2 - t1) / 1e6d, response.code(), msg));
return response.newBuilder()
.body(ResponseBody.create(response.body().contentType(), msg))
.headers(response.headers())
.build();
}
}).build();
}
Then you will need to also take a Context
to you getInstance
method and then call initClient
-- 然后你还需要将一个
Context
带到getInstance
方法,然后调用initClient
-
@NonNull
public static MyApplication getInstance(Context context) {
initClient(context);
Retrofit rf = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create(new GsonBuilder()
.excludeFieldsWithModifiers(Modifier.FINAL, Modifier.TRANSIENT, Modifier.STATIC)
.create()))
.client(CLIENT)
.build();
return rf.create(MyApplication.class);
}
You can also delete your constructor and the context
data member as they are not used. 您也可以删除构造函数和
context
数据成员,因为它们未被使用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.