#android #caching #cache-control #okhttp
#Android #кэширование #контроль кэша #okhttp
Вопрос:
я хочу сказать, что я использую кэширование okhttp с обновлением, но файл кэша не создан, пока я пишу правильный код, потому что я создаю пример приложения, где работа завершена, но когда я использую тот же код в своем проекте, я не понимаю, почему не создать файл кэша.
Вот мой код :
private Context context;
private PrefManager prefManager;
private String BEARER = "Bearer ";
private String APP_JSON = "application/json";
private String OUTPUT_ACCEPT = "Accept";
private String AUTHERIZATION = "Authorization";
private int CACHE_SIZE_BYTES = 10 * 1024 * 1024;
private String TAG = OkHttpClientModule.class.getSimpleName();
@Provides
public OkHttpClient okHttpClient(Cache cache, Interceptor interceptor, StethoInterceptor stethoInterceptor, HttpLoggingInterceptor httpLoggingInterceptor) {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.addInterceptor(interceptor);
builder.cache(cache);
builder.connectTimeout(10, TimeUnit.SECONDS);
builder.writeTimeout(10, TimeUnit.SECONDS);
builder.readTimeout(30, TimeUnit.SECONDS);
if (BuildConfig.DEBUG) {
builder.addNetworkInterceptor(stethoInterceptor);
builder.interceptors().add(httpLoggingInterceptor);
}
OkHttpClient client = builder.build();
return client;
}
@Provides
public PrefManager getManager(Context context) {
return new PrefManager(context);
}
@Provides
public StethoInterceptor getSteltho() {
return new StethoInterceptor();
}
@Provides
public Cache cache(File cacheFile) {
Cache cache = null;
try {
cache = new Cache(cacheFile, CACHE_SIZE_BYTES);
Log.e("TAG", " cache created " cache.directory().getPath());
} catch (Exception e) {
e.printStackTrace();
Log.e("TAG", " cache exception " e.getLocalizedMessage());
}
return cache;
}
@Provides
@RandomUserApplicationScope
public File file(@ApplicationContext Context ctx) {
this.context = ctx;
File file = new File(ctx.getCacheDir(), "httpcache");
return file;
}
@Provides
public Interceptor getIntercepter() {
final String mAuth = "";//Credentials.basic(BaseRequest.AUTH_USERNAME, BaseRequest.AUTH_PASSWORD);
Interceptor headerAuthorizationInterceptor = new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
if (!NetworkUtils.isConnected(context)) {
Log.e(TAG, "response from cache ");
Request request = chain.request();
CacheControl cacheControl = new
CacheControl.Builder().maxStale(1,
TimeUnit.DAYS).build();
request = request.newBuilder().cacheControl(cacheControl).build();
String rawJson = chain.proceed(request).body().string();
Log.e(BuildConfig.APPLICATION_ID, String.format("req response cache raw JSON response is: %s", rawJson));
return chain.proceed(request);
} else {
Log.e(TAG, "response from network");
CacheControl cacheControl = new CacheControl.Builder().maxAge(1, TimeUnit.HOURS).build();
prefManager = new PrefManager(context);
String token = prefManager.getPreference(AppConstant.HEADER_TOKEN);
Request.Builder request = chain.request().newBuilder();
request.addHeader(OUTPUT_ACCEPT, APP_JSON);
request.addHeader(AUTHERIZATION, BEARER token);
request.header(CACHE_CONTROL, cacheControl.toString());
//request.cacheControl(CacheControl.FORCE_CACHE);
Response response = chain.proceed(request.build());
return response;
}
}
};
return headerAuthorizationInterceptor;
}
@Provides
public HttpLoggingInterceptor httpLoggingInterceptor() {
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
return httpLoggingInterceptor;
}
И я проверяю файл кэша в проводнике, но показываю здесь
Ответ №1:
Вы можете создать контекст в вашем MainActivity, как показано ниже:
public static Context mContext;
В вашем onCreate() вы можете добавить:
mContext = getApplicationContext();
Затем, в отдельном файле, пример RetrofitCachingInstance:
public class RetrofitCachingInstance {
private static final Interceptor REWRITE_CACHE_CONTROL_INTERCEPTOR = chain -> {
Response originalResponse = chain.proceed(chain.request());
return originalResponse.newBuilder()
.removeHeader("Pragma")
.header("Cache-Control",
String.format(Locale.ENGLISH, "max-age=%d", 60))
.build();
};
private static Retrofit retrofit;
private static final String BASE_URL = "YOUR_JSON_URL";
public static Retrofit getRetrofitInstance() {
if (retrofit == null) {
OkHttpClient.Builder client = new OkHttpClient.Builder();
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
client.addInterceptor(loggingInterceptor);
client.addNetworkInterceptor(REWRITE_CACHE_CONTROL_INTERCEPTOR);
client.addInterceptor(provideOfflineCacheInterceptor());
client.cache(getCache(MainActivity.mContext));
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client.build())
.addConverterFactory(GsonConverterFactory.create())
// using Gson for deserialization in this case
.build();
}
return retrofit;
}
private static Interceptor provideOfflineCacheInterceptor() {
return chain -> {
try {
return chain.proceed(chain.request());
} catch (Exception e) {
CacheControl cacheControl = new CacheControl.Builder()
.onlyIfCached()
.maxStale(2, TimeUnit.DAYS)
// accept cached responses up to 2 days old, else hit network request again
.build();
Request offlineCachingRequest = chain.request().newBuilder()
.removeHeader("Pragma")
.cacheControl(cacheControl)
.build();
return chain.proceed(offlineCachingRequest);
}
};
}
private static Cache getCache(Context context) {
int cacheSize = 10 * 1024 * 1024; // Cache size is only 10 MB maximum
return new Cache(MainActivity.mContext.getCacheDir(), cacheSize);
}
}
Это должно сработать. Надеюсь, это полезно.