दिलचस्प पोस्ट
जावा में कोर की संख्या ढूँढना पैसिट_ग्रीड के साथ पैनल पृष्ठभूमि को सशर्त बदलना है? हैश डिफ़ॉल्ट मान का उपयोग करते समय अजीब, अप्रत्याशित व्यवहार (गायब / बदलते मूल्य) उदा। Hash.new () अपने स्थानीय और जिथब रिपॉजिटरी में एक फ़ाइल की अलग-अलग सामग्री कैसे रखनी है? फेसबुक एपीआई – उपयोगकर्ता का पता कैसे प्राप्त करें, फोन #? ES6 वेबपैक का उपयोग करके एक vue.js प्रोजेक्ट में ('@') साइन इन पथ पर उपयोग करके आयात करें क्यूमेक – आउटपुट में एक फाइल कॉपी कैसे करें ओएस एक्स 10.11 पर पीडीएफक सर्वर Excel VBA में इम्प्लिमेंट्स का उपयोग कैसे करें C, C ++, और C # में शून्य का क्या अर्थ है? अजगर वर्ग की प्रतिलिपि कैसे करें? कस्टम सत्यापन विशेषता कैसे बनाएं? कैसे एक WPF नियंत्रण का एक स्क्रीनशॉट लेने के लिए? पहली बार पैनल को एक फ्रेम में क्यों गायब हो जाता है? वादा परिणाम से नोड मॉड्यूल निर्यात करना

ऑफ़लाइन होने पर OKHttp के साथ रेट्रोफ़िट कैश डेटा का उपयोग कर सकते हैं

मैं HTTP प्रतिसाद कैश करने के लिए Retrofit और OKHttp का उपयोग करने की कोशिश कर रहा हूं। मैंने इस संहिता का पालन किया, और इस कोड के साथ समाप्त हुआ:

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

और यह कैओ-कंट्रोल हेडर के साथ मायएपी है I

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

सबसे पहले मैं ऑनलाइन अनुरोध करता हूं और कैश फ़ाइलों की जांच करता हूं। सही JSON प्रतिक्रिया और हेडर हैं। लेकिन जब मैं ऑफ़लाइन अनुरोध करने का प्रयास करता हूं, तो मुझे हमेशा RetrofitError UnknownHostException मिलता है। क्या कैश से उत्तर को रेट्रोफिट पढ़ने के लिए मुझे कुछ और करना चाहिए?

संपादित करें: चूंकि OKHttp 2.0.x HttpResponseCache Cache , setResponseCache setCache

वेब के समाधान से एकत्रित समाधान "ऑफ़लाइन होने पर OKHttp के साथ रेट्रोफ़िट कैश डेटा का उपयोग कर सकते हैं"

रेट्रोफिट 2.x के लिए संपादित करें:

ओकेएचटीपी इंटरसेप्टर ऑफ़लाइन होने पर कैश तक पहुंचने का सही तरीका है:

1) इंटरसेप्टर बनाएँ:

 private static final Interceptor REWRITE_CACHE_CONTROL_INTERCEPTOR = new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Response originalResponse = chain.proceed(chain.request()); if (Utils.isNetworkAvailable(context)) { int maxAge = 60; // read from cache for 1 minute return originalResponse.newBuilder() .header("Cache-Control", "public, max-age=" + maxAge) .build(); } else { int maxStale = 60 * 60 * 24 * 28; // tolerate 4-weeks stale return originalResponse.newBuilder() .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale) .build(); } } 

2) सेटअप क्लाइंट:

 OkHttpClient client = new OkHttpClient(); client.networkInterceptors().add(REWRITE_CACHE_CONTROL_INTERCEPTOR); //setup cache File httpCacheDirectory = new File(context.getCacheDir(), "responses"); int cacheSize = 10 * 1024 * 1024; // 10 MiB Cache cache = new Cache(httpCacheDirectory, cacheSize); //add cache to the client client.setCache(cache); 

3) रेट्रोफिट के लिए ग्राहक जोड़ें

 Retrofit retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .client(client) .addConverterFactory(GsonConverterFactory.create()) .build(); 

इसके अलावा कोसीआरा – बार्टोस कोसारीकी का उत्तर भी देखें । आपको प्रतिक्रिया से कुछ हेडर निकालने की आवश्यकता हो सकती है


OKHttp 2.0.x (मूल उत्तर की जांच करें):

चूंकि OKHttp 2.0.x HttpResponseCache Cache , setResponseCache है setCache । तो आपको इस तरह setCache करना चाहिए:

  File httpCacheDirectory = new File(context.getCacheDir(), "responses"); Cache cache = null; try { cache = new Cache(httpCacheDirectory, 10 * 1024 * 1024); } catch (IOException e) { Log.e("OKHttp", "Could not create http cache", e); } OkHttpClient okHttpClient = new OkHttpClient(); if (cache != null) { okHttpClient.setCache(cache); } String hostURL = context.getString(R.string.host_url); api = new RestAdapter.Builder() .setEndpoint(hostURL) .setClient(new OkClient(okHttpClient)) .setRequestInterceptor(/*rest of the answer here */) .build() .create(MyApi.class); 

मूल उत्तर:

यह पता चला है कि सर्वर प्रतिक्रिया में Cache-Control: public होना आवश्यक है Cache-Control: public OkClient को कैश से पढ़ने के लिए Cache-Control: public

इसके अलावा यदि आप उपलब्ध होने पर नेटवर्क से अनुरोध करना चाहते हैं, तो आपको Cache-Control: max-age=0 अनुरोध शीर्षलेख जोड़ना चाहिए। यह जवाब दिखाता है कि यह कैसे पैरामीट करना है। मैं इसे कैसे इस्तेमाल किया है:

 RestAdapter.Builder builder= new RestAdapter.Builder() .setRequestInterceptor(new RequestInterceptor() { @Override public void intercept(RequestFacade request) { request.addHeader("Accept", "application/json;versions=1"); if (MyApplicationUtils.isNetworkAvailable(context)) { int maxAge = 60; // read from cache for 1 minute request.addHeader("Cache-Control", "public, max-age=" + maxAge); } else { int maxStale = 60 * 60 * 24 * 28; // tolerate 4-weeks stale request.addHeader("Cache-Control", "public, only-if-cached, max-stale=" + maxStale); } } }); 

ऊपर के सभी anwsers मेरे लिए काम नहीं किया मैंने दोबारा 2.0.0-बीटा 2 में ऑफ़लाइन कैश को लागू करने की कोशिश की मैंने okHttpClient.networkInterceptors() विधि का उपयोग करते हुए एक इंटरसेप्टर जोड़ा था लेकिन java.net.UnknownHostException प्राप्त किया था। java.net.UnknownHostException जब मैंने कैश ऑफ़लाइन का उपयोग करने की कोशिश की यह पता चला कि मुझे okHttpClient.interceptors() जोड़ना था

समस्या यह थी कि कैश फ्लैश मेमोरी के लिए नहीं लिखा गया था क्योंकि सर्वर ने लौटा Pragma:no-cache जो प्रतिक्रिया को संग्रहित करने से ओकेएचटीपी को रोकता है। ऑफ़लाइन कैश अनुरोध हैडर मान को संशोधित करने के बाद भी काम नहीं किया। कुछ परीक्षण और त्रुटि के बाद मुझे अनुरोध के बजाय response.newBuilder().removeHeader("Pragma"); को निकालकर बैकएंड पक्ष को संशोधित किए बिना काम करने के लिए कैश मिला है – response.newBuilder().removeHeader("Pragma");

रेट्रोफ़िट: 2.0.0-बीटा 2 ; ओकेएचटीपी: 2.5.0

 OkHttpClient okHttpClient = createCachedClient(context); Retrofit retrofit = new Retrofit.Builder() .client(okHttpClient) .baseUrl(API_URL) .addConverterFactory(GsonConverterFactory.create()) .build(); service = retrofit.create(RestDataResource.class); 

 private OkHttpClient createCachedClient(final Context context) { File httpCacheDirectory = new File(context.getCacheDir(), "cache_file"); Cache cache = new Cache(httpCacheDirectory, 20 * 1024 * 1024); OkHttpClient okHttpClient = new OkHttpClient(); okHttpClient.setCache(cache); okHttpClient.interceptors().add( new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Request originalRequest = chain.request(); String cacheHeaderValue = isOnline(context) ? "public, max-age=2419200" : "public, only-if-cached, max-stale=2419200" ; Request request = originalRequest.newBuilder().build(); Response response = chain.proceed(request); return response.newBuilder() .removeHeader("Pragma") .removeHeader("Cache-Control") .header("Cache-Control", cacheHeaderValue) .build(); } } ); okHttpClient.networkInterceptors().add( new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Request originalRequest = chain.request(); String cacheHeaderValue = isOnline(context) ? "public, max-age=2419200" : "public, only-if-cached, max-stale=2419200" ; Request request = originalRequest.newBuilder().build(); Response response = chain.proceed(request); return response.newBuilder() .removeHeader("Pragma") .removeHeader("Cache-Control") .header("Cache-Control", cacheHeaderValue) .build(); } } ); return okHttpClient; } 

 public interface RestDataResource { @GET("rest-data") Call<List<RestItem>> getRestData(); } 

मेरा समाधान:

 private BackendService() { httpCacheDirectory = new File(context.getCacheDir(), "responses"); int cacheSize = 10 * 1024 * 1024; // 10 MiB Cache cache = new Cache(httpCacheDirectory, cacheSize); httpClient = new OkHttpClient.Builder() .addNetworkInterceptor(REWRITE_RESPONSE_INTERCEPTOR) .addInterceptor(OFFLINE_INTERCEPTOR) .cache(cache) .build(); Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.backend.com") .client(httpClient) .addConverterFactory(GsonConverterFactory.create()) .build(); backendApi = retrofit.create(BackendApi.class); } private static final Interceptor REWRITE_RESPONSE_INTERCEPTOR = chain -> { Response originalResponse = chain.proceed(chain.request()); String cacheControl = originalResponse.header("Cache-Control"); if (cacheControl == null || cacheControl.contains("no-store") || cacheControl.contains("no-cache") || cacheControl.contains("must-revalidate") || cacheControl.contains("max-age=0")) { return originalResponse.newBuilder() .header("Cache-Control", "public, max-age=" + 10) .build(); } else { return originalResponse; } }; private static final Interceptor OFFLINE_INTERCEPTOR = chain -> { Request request = chain.request(); if (!isOnline()) { Log.d(TAG, "rewriting request"); int maxStale = 60 * 60 * 24 * 28; // tolerate 4-weeks stale request = request.newBuilder() .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale) .build(); } return chain.proceed(request); }; public static boolean isOnline() { ConnectivityManager cm = (ConnectivityManager) MyApplication.getApplication().getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo netInfo = cm.getActiveNetworkInfo(); return netInfo != null && netInfo.isConnectedOrConnecting(); } 

@ कोशियारा-बर्टोस्ज़-कासरजीक्की के उत्तर पर निर्माण, मैंने एक नमूना प्रोजेक्ट बनाया है जो मेमोरी-> डिस्क-> नेटवर्क से रेट्रोफाइट, ओक्टेप, आरएक्सजावा और पेरावा का उपयोग करके ठीक से लोड करता है। https://github.com/digitalbuddha/StoreDemo

जवाब हाँ है, ऊपर दिए गए उत्तरों के आधार पर, मैंने सभी संभावित उपयोग मामलों को सत्यापित करने के लिए यूनिट परीक्षण लिखना शुरू कर दिया है:

  • ऑफ़लाइन होने पर कैश का उपयोग करें
  • कैश्ड प्रतिक्रिया का उपयोग पहले समाप्त होने तक, फिर नेटवर्क
  • कुछ अनुरोधों के लिए पहले कैश नेटवर्क का उपयोग करें
  • कुछ प्रतिक्रियाओं के लिए कैश में न रखें

मैंने ओएचटीपीटी कैश को आसानी से कॉन्फ़िगर करने के लिए एक छोटा सहायक एबिलिटी बनाई, आप यहां गिटब पर संबंधित यूनिट देख सकते हैं: https://github.com/ncornette/OkCacheControl/blob/master/okcache-control/src/test/java/com/ ncornette / कैश / OkCacheControlTest.java

अकेले जब ऑफ़लाइन कैश के इस्तेमाल को दर्शाता है:

 @Test public void test_USE_CACHE_WHEN_OFFLINE() throws Exception { //given givenResponseInCache("Expired Response in cache", -5, MINUTES); given(networkMonitor.isOnline()).willReturn(false); //when //This response is only used to not block when test fails mockWebServer.enqueue(new MockResponse().setResponseCode(404)); Response response = getResponse(); //then then(response.body().string()).isEqualTo("Expired Response in cache"); then(cache.hitCount()).isEqualTo(1); } 

जैसा कि आप देख सकते हैं, कैश का उपयोग तब भी किया जा सकता है जब इसकी समय सीमा समाप्त हो गई हो। आशा है कि यह मदद करेगा

रेट्रोफाइट 2 और ओकेएचटीटीपी 3 के साथ कैश:

 OkHttpClient client = new OkHttpClient .Builder() .cache(new Cache(App.sApp.getCacheDir(), 10 * 1024 * 1024)) // 10 MB .addInterceptor(new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); if (NetworkUtils.isNetworkAvailable()) { request = request.newBuilder().header("Cache-Control", "public, max-age=" + 60).build(); } else { request = request.newBuilder().header("Cache-Control", "public, only-if-cached, max-stale=" + 60 * 60 * 24 * 7).build(); } return chain.proceed(request); } }) .build(); 

NetworkUtils.is नेटवर्क उपलब्ध () स्थैतिक विधि:

 public static boolean isNetworkAvailable(Context context) { ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); return activeNetwork != null && activeNetwork.isConnectedOrConnecting(); } 

फिर बस पुरानी पुरानी निर्माता को क्लाइंट जोड़ें:

 Retrofit retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .client(client) .addConverterFactory(GsonConverterFactory.create()) .build(); 

मूल स्रोत: https://newfivefour.com/android-retrofit2-okhttp3-cache-network-request-offline.html