离线缓存 okhttp + 改造不起作用
Offline cache okhttp + retrofit not working
我正在尝试在没有可用网络时激活用于离线浏览的缓存。
不幸的是,它无法正常工作,当我调试应用程序时,正在访问拦截器或缓存。
所以我猜下面的代码有问题。
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);
}
}
你的初始化块是非静态的,但你从来没有分配这个对象的实例,所以它永远不会得到 运行。看起来您打算初始化静态成员 CLIENT
。因为此初始化最终取决于 Context
,所以您无法将其转换为静态初始化块。将其转换为采用 Context
参数的初始化方法。注意:我还将 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();
}
那你还需要带一个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);
}
您还可以删除构造函数和 context
数据成员,因为它们未被使用。
我正在尝试在没有可用网络时激活用于离线浏览的缓存。 不幸的是,它无法正常工作,当我调试应用程序时,正在访问拦截器或缓存。
所以我猜下面的代码有问题。
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);
}
}
你的初始化块是非静态的,但你从来没有分配这个对象的实例,所以它永远不会得到 运行。看起来您打算初始化静态成员 CLIENT
。因为此初始化最终取决于 Context
,所以您无法将其转换为静态初始化块。将其转换为采用 Context
参数的初始化方法。注意:我还将 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();
}
那你还需要带一个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);
}
您还可以删除构造函数和 context
数据成员,因为它们未被使用。