2017-06-18 157 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每次都執行網絡請求。 –