我只想缓存某些电话,而不是全部。这是我现在的代码,但它将影响所有的更新调用:
int cacheSize = 10 * 1024 * 1024; // 10 MB
Cache cache = new Cache(getCacheDir(), cacheSize);
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.cache(cache)
.build();
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl("http://10.0.2.2:3000/")
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create());
Retrofit retrofit = builder.build(); 当我只想为那个调用做缓存时,我能在头中放些什么吗?
例如:
//我在想,我可以在头上放点东西。我只想缓存客户端(android)端的调用。所以我想改造可以记住响应并为下一次调用缓存它,但我不想让所有的调用,仅仅是我想要的,也许1或2,其余的可以一直连接到服务器。这是怎么搞到的?
@Headers("Cache-Control:????XXXXX) //is it possible this way ?, how ?
@GET("getBusiness.action")// Store information
Call<RestaurantInfoModel> getRestaurantInfo(@Query("userId") String userId,@Query("businessId") String businessId);更新:
以下是我现在尝试过的:
下面是构建okhttpclient的方法:
final OkHttpClient.Builder builder = new OkHttpClient.Builder();
int cacheSize = 10 * 1024 * 1024; // 10 MB
Cache cache = new Cache(getCacheDir(), cacheSize);
if (BuildConfig.RETROFIT_LOG_ALL) {
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
builder.addInterceptor(logging);
}
builder.cache(cache);
return builder.build();稍后,我将它添加到改造中,它可以工作,但似乎不适用于缓存。让我们在不向okhttp添加缓存的情况下看到头响应:
Content-Type: application/json; charset=utf-8
06-18 17:54:58.044 11233-11735/com.mobile.myapp.staging D/OkHttp: Connection: close
06-18 17:54:58.044 11233-11735/com.mobile.myapp.staging D/OkHttp: Transfer-Encoding: chunked
06-18 17:54:58.044 11233-11735/com.mobile.myapp.staging D/OkHttp: X-Powered-By: Express
06-18 17:54:58.044 11233-11735/com.mobile.myapp.staging D/OkHttp: Vary: Origin
06-18 17:54:58.044 11233-11735/com.mobile.myapp.staging D/OkHttp: Access-Control-Allow-Credentials: true
06-18 17:54:58.044 11233-11735/com.mobile.myapp.staging D/OkHttp: Cache-Control: public, max-age=0
06-18 17:54:58.044 11233-11735/com.mobile.myapp.staging D/OkHttp: ETag: W/"39ba-G9evSsiVDp9GAVGu1Mk4ag"
06-18 17:54:58.044 11233-11735/com.mobile.myapp.staging D/OkHttp: Date: Sun, 18 Jun 2017 10:54:58 GMT下面是我所做的测试,看看缓存是否有效。我使用以下方法向api发出请求:
public interface CountriesApi {
@GET("countries")
@Headers({"Content-Type:application/json"})
Observable<List<CountryModel>> getCountries();
}后来,我关闭了android设备上的互联网,当然,我还在应用程序中尝试再次拨打同样的电话。但是我却被改造了,抱怨没有网络连接。相反,它应该从缓存中得到。你知道怎么回事吗?
java.net.SocketException: Network is unreachable at
java.net.PlainSocketImpl.socketConnect(Native Method) at
java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:334) at
java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:196)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:178) at
java.net.SocksSocketImpl.connect(SocksSocketImpl.java:356) at
java.net.Socket.connect(Socket.java:586) at
okhttp3.internal.platform.AndroidPlatform.connectSocket(AndroidPlatform.java:63)
at
okhttp3.internal.connection.RealConnection.connectSocket(RealConnection.java:223)
at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:149)
at
okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:192)
at
okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:121)
at
okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:100)
at
okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42)
at
okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at
okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
at
okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at
okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
at
okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at
okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:120)
at
okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at
okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at
okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.java:211)
at
okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at
okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at
com.mobile.retrofit.NetworkSessionManager.intercept(NetworkSessionManager.java:38)
at
okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at
okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:185) at
okhttp3.RealCall.execute(RealCall.java:69) at
retrofit2.OkHttpCall.execute(OkHttpCall.java:180) at
retrofit2.adapter.rxjava2.CallExecuteObservable.subscribeActual(CallExecuteObservable.java:41)
at io.reactivex.Observable.subscribe(Observable.java:10842) at
retrofit2.adapter.rxjava2.BodyObservable.subscribeActual(BodyObservable.java:34)
at io.reactivex.Observable.subscribe(Observable.java:10842) at
io.reactivex.internal.operators.observable.ObservableFlatMap.subscribeActual(ObservableFlatMap.java:55)
at io.reactivex.Observable.subscribe(Observable.java:10842) at
io.reactivex.internal.operators.observable.ObservableSubscribeOn$SubscribeTask.run(ObservableSubscribeOn.java:96)
at io.reactivex.Scheduler$DisposeTask.run(Scheduler.java:452) at
io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:61)
at
io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:52)
at java.util.concurrent.FutureTask.run(FutureTask.java:237) at
java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:272)
at
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
at java.lang.Thread.run(Thread.java:761) 发布于 2017-06-18 10:25:46
做缓存(doc)的是缓存(doc)库,它主要由响应头驱动。您应该检查它们并验证是否缓存了API响应。OkHttp测井拦截器应该有助于调试。
要检查是否发生了网络请求,请使用HttpLoggingInterceptor作为网络拦截器,而不是应用程序拦截器(参见https://github.com/square/okhttp/wiki/Interceptors):
HttpLoggingInterceptor interceptor = HttpLoggingInterceptor();
interceptor.setLevel(Level.BASIC);
OkHttpClient client = new OkHttpClient.Builder()
.addNetworkInterceptor(new LoggingInterceptor())
.build();当请求由缓存处理时,将不会调用网络拦截器。
下一步将视情况而定。
1)缓存所有API请求。
然后,您应该能够对不希望缓存的方法使用注释@Header(“cache -Control: no-cache")。
2)未缓存所有API请求。
然后,您可以更改API (添加适当的缓存头),也可以为OkHttp实现网络拦截器,这将修改响应(报头)。您可以在以下回复中找到一些启示:OKHttp可在脱机时使用缓存数据吗?
发布于 2021-02-17 09:00:57
使用自定义注释
@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
annotation class Cacheable
class MainInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val request = chain.request()
val builder = request.newBuilder()
request.tag(Invocation::class.java)?.let {
if (!it.method().isAnnotationPresent(Cacheable::class.java)) {
builder.cacheControl(CacheControl.Builder()
.noStore()
.build())
return chain.proceed(builder.build())
}
try {
builder.cacheControl(CacheControl.FORCE_NETWORK)
return chain.proceed(builder.build())
} catch (e: Throwable) {
e.printStackTrace()
}
builder.cacheControl(CacheControl.Builder()
.maxStale(Int.MAX_VALUE, TimeUnit.DAYS)
.build())
}
return chain.proceed(builder.build())
}
}
interface ServerApi {
@Cacheable
@GET("some_path")
fun getSmth(): Call<ResponseBody>
}不要丢失将缓存添加到okhttp实例
OkHttpClient.Builder()
.cache(Cache(context.cacheDir, 10 * 1024 * 1024L))
.addInterceptor(MainInterceptor())
//...发布于 2021-05-23 10:12:40
我也在寻找同样的解决方案,他们想出了这样的解决方案:
首先创建一个Singleton Retrofit类:
public class RetrofitClient {
private static final String BASE_URL = "BASE URL HERE...";
private static RetrofitClient mInstance;
private final Retrofit retrofit;
private final Retrofit retrofitCache;
private static final String HEADER_CACHE_CONTROL = "Cache-Control";
private static final String HEADER_PRAGMA = "Pragma";
int cacheSize = 10 * 1024 * 1024; // 10 MB
public static synchronized RetrofitClient getInstance(Context context) {
if (mInstance == null) {
mInstance = new RetrofitClient(context);
}
return mInstance;
}
private RetrofitClient(Context context) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
retrofitCache = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(okHttpClient(context))
.addConverterFactory(GsonConverterFactory.create())
.build();
}
public ApiInterface getApi() {
return retrofit.create(ApiInterface.class);
}
public ApiInterface getCachedApi() {
return retrofitCache.create(ApiInterface.class);
}
Interceptor networkInterceptor() {
return chain -> {
CacheControl cacheControl = new CacheControl.Builder()
.maxAge(5, TimeUnit.MINUTES) //cache validity time
.build();
Response response = chain.proceed(chain.request());
return response.newBuilder()
.removeHeader(HEADER_PRAGMA)
.removeHeader(HEADER_CACHE_CONTROL)
.header(HEADER_CACHE_CONTROL, cacheControl.toString())
.build();
};
}
OkHttpClient okHttpClient(Context context) {
Cache cache = new Cache(context.getCacheDir(), cacheSize);
return new OkHttpClient.Builder()
.cache(cache)
.addNetworkInterceptor(networkInterceptor())
.build();
}}
然后创建如下API接口:
public interface ApiInterface {
@GET("apiEndPoint")
Call<ResponseBody> getData();
}然后在RetrofitClient中使用Activity,如下所示:
//Without Cache
Call<AboutResponse> call =
RetrofitClient.getInstance(this)
.getApi()
.getAbout();
/With Cache
Call<AboutResponse> call =
RetrofitClient.getInstance(this)
.getCachedApi()
.getAbout();https://stackoverflow.com/questions/44613128
复制相似问题