2017-06-18 161 views
0

我只想缓存某些不是全部的调用。这是代码我现在有,但它会影响所有改装电话:Retrofit2 - 如何仅缓存某些API调用

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); 

UPDATE

这里是我现在已经尝试:

这是我如何打造出来的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) 
+0

那么,我想你应该首先检查https://stackoverflow.com/a/23503804/3225458并实现拦截器,因为这里提到。 – rom4ek

回答

1

这是OkHttp库谁做了caching (doc),它主要由响应头驱动。您应该检查它们并验证API响应是否被缓存。 OkHttp logging interceptor应该有助于调试。

要检查网络请求正在发生的事情用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请求都被缓存。

然后,您应该可以使用注释@Headers(“Cache-Control:no-cache”)查找您想要缓存的不要的方法。

2)所有的API请求都没有被缓存。

然后,您可以更改API(添加适当的缓存标头),也可以为OkHttp实现网络拦截器,这将修改响应(标头)。你可以在这个回复中找到一些灵感:Can Retrofit with OKHttp use cache data when offline

+0

如何从日志中判断它是否是一个缓存副本?我想如果我切断了互联网,我可以很容易地判断,但是翻新引发了一个例外,即没有网络连接,我没有看到或得到任何API响应。我还注意到我的最大年龄是0,这很重要。我正在让okhttpclient使用缓存对象来配置缓存,这取决于我的帖子在构建器中使用缓存对象。 – j2emanue

+0

您可以将日志拦截器添加为网络拦截器(Ob的Builder对象上的addNetworkInterceptor)。网络拦截器仅在访问网络时被调用,因此缓存的响应不会显示在日志中。我会扩大回应,以包括这一点。 –

+0

是的,由API发送的Cache-Control:max-age = 0头是重要的,并且会强制OkHttp每次都执行网络请求。 –