Estou tentando usar o Retrofit & OKHttp para armazenar em cache as respostas HTTP. Eu segui essa essência e, acabei com este código:
File httpCacheDirectory = new File(context.getCacheDir(), "responses");
HttpResponseCache httpResponseCache = null;
try {
httpResponseCache = new HttpResponseCache(httpCacheDirectory, 10 * 1024 * 1024);
} catch (IOException e) {
Log.e("Retrofit", "Could not create http cache", e);
}
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setResponseCache(httpResponseCache);
api = new RestAdapter.Builder()
.setEndpoint(API_URL)
.setLogLevel(RestAdapter.LogLevel.FULL)
.setClient(new OkClient(okHttpClient))
.build()
.create(MyApi.class);
E esse é o MyApi com os cabeçalhos de controle de cache
public interface MyApi {
@Headers("Cache-Control: public, max-age=640000, s-maxage=640000 , max-stale=2419200")
@GET("/api/v1/person/1/")
void requestPerson(
Callback<Person> callback
);
Primeiro solicito on-line e verifico os arquivos de cache. A resposta JSON correta e os cabeçalhos estão lá. Mas quando tento solicitar offline, sempre entendo RetrofitError UnknownHostException
. Há mais alguma coisa que devo fazer para fazer com que o Retrofit leia a resposta do cache?
EDIT:
Como OKHttp 2.0.x HttpResponseCache
é Cache
, setResponseCache
ésetCache
Cache-Control: s-maxage=1209600, max-age=1209600
, não sei se é suficiente.public
palavra - chave precisava estar no cabeçalho de resposta para fazê-la funcionar offline. Porém, esses cabeçalhos não permitem que o OkClient use a rede quando houver disponível. Existe alguma maneira de definir a política / estratégia de cache para usar a rede quando disponível?max-stale + max-age
passado, ele solicita da rede. Mas quero definir o máximo de uma semana. Isso faz com que leia a resposta do cache, mesmo se houver rede disponível.Respostas:
Edite para o Retrofit 2.x:
O OkHttp Interceptor é o caminho certo para acessar o cache quando offline:
1) Criar interceptor:
2) Cliente de instalação:
3) Adicione o cliente para modernizar
Além disso, verifique @kosiara - Bartosz Kosarzycki 's resposta . Pode ser necessário remover algum cabeçalho da resposta.
OKHttp 2.0.x (verifique a resposta original):
Desde OKHttp 2.0.x
HttpResponseCache
éCache
,setResponseCache
ésetCache
. Então você devesetCache
assim:Resposta original:
Acontece que a resposta do servidor deve ter
Cache-Control: public
que ser feitaOkClient
para ler do cache.Além disso, se você desejar solicitar da rede quando disponível, adicione o
Cache-Control: max-age=0
cabeçalho da solicitação. Esta resposta mostra como fazê-lo parametrizado. Foi assim que eu o usei:fonte
HttpResponseCache has been renamed to Cache.** Install it with OkHttpClient.setCache(...) instead of OkHttpClient.setResponseCache(...)
.if (Utils.isNetworkAvailable(context))
correto ou deve ser revertido, ou sejaif (!Utils.isNetworkAvailable(context))
?public okhttp3.Response intercept(Chain chain) throws IOException
nunca é chamado, ele só é chamado quando estou onlineTodas as respostas acima não funcionaram para mim. Tentei implementar o cache offline no retrofit 2.0.0-beta2 . Adicionei um interceptador usando o
okHttpClient.networkInterceptors()
método, mas recebijava.net.UnknownHostException
quando tentei usar o cache offline. Acabou que eu tinha que adicionarokHttpClient.interceptors()
também.O problema era que o cache não foi gravado no armazenamento flash porque o servidor retornou, o
Pragma:no-cache
que impede que o OkHttp armazene a resposta. O cache offline não funcionou mesmo depois de modificar os valores do cabeçalho da solicitação. Após algumas tentativas e erros, consegui que o cache funcionasse sem modificar o lado do back-end, removendo o pragma da resposta em vez da solicitação -response.newBuilder().removeHeader("Pragma");
Retrofit: 2.0.0-beta2 ; OkHttp: 2.5.0
...
...
fonte
interceptors ()
enetworkInterceptors ()
são idênticos. Por que você duplicou isso?.networkInterceptors().add()
einterceptors().add()
?Minha solução:
fonte
A resposta é SIM, com base nas respostas acima, comecei a escrever testes de unidade para verificar todos os possíveis casos de uso:
Eu construí uma pequena biblioteca auxiliar para configurar o cache OKHttp facilmente, você pode ver o unittest relacionado aqui no Github: https://github.com/ncornette/OkCacheControl/blob/master/okcache-control/src/test/java/com/ ncornette / cache / OkCacheControlTest.java
Unittest que demonstra o uso do cache quando offline:
Como você pode ver, o cache pode ser usado mesmo que tenha expirado. Espero que ajude.
fonte
com base @ do kosiara-bartosz-kasarzycki resposta , eu criei um projeto de exemplo que propriamente cargas de memória-> disk> rede usando retrofit, okhttp, rxjava e goiaba. https://github.com/digitalbuddha/StoreDemo
fonte
Cache com Retrofit2 e OkHTTP3:
Método estático NetworkUtils.isNetworkAvailable ():
Em seguida, basta adicionar o cliente ao construtor de retrofit:
Fonte original: https://newfivefour.com/android-retrofit2-okhttp3-cache-network-request-offline.html
fonte