2017-06-18 3 views
0

Ich möchte nur bestimmte Anrufe nicht alle zwischenspeichern. Dies ist der Code, den ich jetzt habe, aber es wird alle Nachrüst-Anrufe betreffen:Retrofit2 - wie nur bestimmte API-Aufrufe zwischenspeichern

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

Gibt es etwas, was ich vielleicht in der Kopfzeile setzen kann, wenn ich nur das Caching für diesen Anruf machen will?

Zum Beispiel:

// Ich dachte ich wäre genug, etwas in den Kopf zu setzen. Ich möchte nur die Anrufe auf dem Client (Android) Ende zwischenspeichern. Also dachte ich, Retrofit könnte sich an die Antwort erinnern und es für den nächsten Anruf zwischenspeichern, aber ich will es nicht für alle meine Anrufe, nur die, die ich will, vielleicht 1 oder 2. Der Rest kann die ganze Zeit mit dem Server verbinden. Wie wird das erreicht?

@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:

Hier ist, was ich habe jetzt versucht:

Hier ist, wie ich die okhttpclient bauen aus:

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

später ich es in den nachrüsten und es funktioniert, aber nicht mit Caching scheint es. Läßt die Header-Antwort siehe Caching okhttp ohne Zugabe:

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 

So, hier ist der Test i-Caching tat, um zu sehen, ob funktioniert. Ich habe eine Anfrage an der api mit diesem:

public interface CountriesApi { 
    @GET("countries") 
    @Headers({"Content-Type:application/json"}) 
    Observable<List<CountryModel>> getCountries(); 
} 

dann danach i SHUTDOWN dem Internet auf dem Android-Gerät und versuchte es erneut teh gleichen Anruf zu tun, während noch in der App natürlich. Stattdessen habe ich nachgerüstet, dass es keine Netzwerkverbindung gibt. stattdessen sollte es gerade aus dem Cache gekommen sein. irgendeine Idee was ist falsch?

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

Nun, ich denke, Sie sollten zuerst überprüfen https://StackOverflow.com/a/23503804/3225458 und implementieren Interceptor wie dort erwähnt. – rom4ek

Antwort

1

Es ist die OkHttp Bibliothek, die die caching (doc) tut und es ist in erster Linie durch Response-Header angetrieben. Sie sollten sie überprüfen und überprüfen, ob API-Antworten überhaupt zwischengespeichert werden. OkHttp logging interceptor sollte beim Debuggen helfen.

Um zu überprüfen, ob Netzwerkanforderung HttpLoggingInterceptor als Netzwerk-Interceptor verwenden geschieht, nicht Anwendung Interceptor (siehe https://github.com/square/okhttp/wiki/Interceptors):

HttpLoggingInterceptor interceptor = HttpLoggingInterceptor(); 
interceptor.setLevel(Level.BASIC); 
OkHttpClient client = new OkHttpClient.Builder() 
.addNetworkInterceptor(new LoggingInterceptor()) 
.build(); 

Netzwerk Abfangjäger nicht Anforderung aufgerufen werden, wenn durch Cache behandelt wird.

Der nächste Schritt hängt von der Situation ab.

1) Alle API-Anfragen werden zwischengespeichert.

Dann sollten Sie in der Lage sein Annotation @Headers ("Cache-Control: no-cache") für Methoden zu verwenden, die Sie nicht zwischenspeichern möchten.

2) Alle API-Anfragen werden nicht zwischengespeichert.

Dann können Sie entweder Ihre API ändern (richtige Cache-Header hinzufügen) oder Sie können Netzwerk-Interceptor für OkHttp implementieren, die Antworten (Header) ändern wird. Sie können einige Inspiration in dieser Antwort finden: Can Retrofit with OKHttp use cache data when offline

+0

Wie kann ich aus den Protokollen sagen, ob es eine Cache-Kopie ist? Ich dachte, wenn ich das Internet schneiden würde ich leicht sagen, aber Retrofit wirft eine Ausnahme, dass es keine Netzwerkverbindung gibt und ich sehe oder bekomme keine API-Antwort. Ich bemerkte auch, dass mein Max-Alter 0 war, ist das wichtig. Ich ließ okhttpclient den Cache mit dem Cache-Objekt konfigurieren, das er im Builder gemäß meinem Post benötigt. – j2emanue

+0

Sie können den Logging Interceptor als Netzwerk-Interceptor hinzufügen (addNetworkInterceptor für das Builder-Objekt von Ob). Der Netzwerk-Interceptor wird nur beim Zugriff auf das Netzwerk aufgerufen, sodass zwischengespeicherte Antworten nicht im Protokoll angezeigt werden. Ich werde die Antwort erweitern, um dies zu berücksichtigen. –

+0

Und ja, Cache-Control: Max-Age = 0 Header von API gesendet ist wichtig und wird OkHttp zwingen, die Netzwerkanforderung jedes Mal zu tun. –