2016-11-10 13 views
5

के साथ अनचेक किया प्रतीत होता है मैं रेट्रोफिट (2.1.0) और ओकेएचटीपी (3.3.1) का उपयोग कर एक HTTP कैश सेट करने का प्रयास कर रहा हूं। मैंने इस विषय से संबंधित कई पदों को देखा है, लेकिन उनमें से कोई भी मदद नहीं करता है।OkHttp3 कैश रेट्रोफिट 2

मैंने कैश कैसे काम करता है यह देखने के लिए मैंने कुछ यूनिट परीक्षण लिखे हैं। यह ठीक काम करता है, लेकिन एक बार मेरे ऐप में एकीकृत, जादू समाप्त होता है। मैं आपको पहले अपना कार्यान्वयन दिखाऊंगा और फिर मेरी कुछ जांच समझाऊंगा।

private static final Interceptor INTERCEPTOR_REQUEST_ADD_CHECKSUM = new Interceptor() { 
     @Override 
     public Response intercept(Interceptor.Chain chain) throws IOException { 
      HttpUrl url = chain.request().url(); 
      url = url.newBuilder().addQueryParameter("rd", "random1").addQueryParameter("chk","check1").build(); 
      Request request = chain.request().newBuilder().url(url).build(); 
      return chain.proceed(request); 
     } 
    }; 
:

private final Interceptor INTERCEPTOR_RESPONSE_SET_CACHE = new Interceptor() { 

     @Override 
     public Response intercept(Chain chain) throws IOException { 
      Response response = chain.proceed(chain.request()); 
      response = response.newBuilder() 
        .header("Cache-Control", "max-age=600") //+ Integer.toString(3600 * 5) 
        .build(); 
      return response; 
     } 
    }; 

पिछले इंटरसेप्टर 2 URL पैरामीटर जोड़ देता है:

OkHttpClient.Builder httpBuilder = new OkHttpClient.Builder(); 
    HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(); 
    interceptor.setLevel(HttpLoggingInterceptor.Level.HEADERS); 

    OkHttpClient client = httpBuilder 
      .addNetworkInterceptor(INTERCEPTOR_RESPONSE_SET_CACHE) 
      .addNetworkInterceptor(INTERCEPTOR_REQUEST_ADD_CHECKSUM) 
      .addInterceptor(loggingInterceptor) 
      .cache(cacheHttpClient).build(); 

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

यहाँ इंटरसेप्टर कैश नियंत्रण स्थापित करने के लिए एक हेडर को जोड़े जाता है:

सबसे पहले, यहाँ मेरी रेट्रोफिट इन्स्टेन्शियशन है

अंत में, मेरी सेवा का एक तरीका:

@Headers("Cache-Control: public, max-stale=500") 
@GET("/get_data") 
Call<DataResponse> getData(@Query("year") int year, @Query("month") int month, @Query("day") int day); 

मेरी जांच के बारे में, मैं क्या हो रहा है यह देखने के लिए एक इंटरसेप्टर लॉगर (ऐप पक्ष, नेटवर्क नहीं) स्थापित करता हूं। मैं अपने लॉग में "कैश-कंट्रोल: पब्लिक, मैक्स-स्टाइल = 500" जैसे लाइन देख सकता हूं। इसका मतलब है (कम से कम मेरे लिए) कि हेडर को कैश की जांच करने के लिए OkHttp क्लाइंट को अवसर देना चाहिए।

कैश स्वयं को सही ढंग से प्रारंभ किया गया प्रतीत होता है। जब मैं इसे बनाता हूं, तो मैं प्रारंभिक बल को बल देता हूं और कैश में मौजूद सभी यूआरएल लॉग करता हूं। यह इस प्रकार से कार्यान्वित किया जाता है है:

File httpCacheDirectory = new File(getCacheDir(), "responses"); 
     httpCacheDirectory.getParentFile().mkdirs(); 
     int cacheSize = 10 * 1024 * 1024; // 10 MiB 
     Cache cache = new Cache(httpCacheDirectory, cacheSize); 
     try { 
      cache.initialize(); 
      Iterator<String> iterator = cache.urls(); 
      Log.i(TAG, "URLs in cacheHttpClient : "); 
      while (iterator.hasNext()) { 
       Log.i(TAG, iterator.next()); 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
      Log.i(TAG, "CACHE NOT INIT"); 
     } 

जब मैं वाईफ़ाई के साथ अपने एप्लिकेशन उपलब्ध लॉन्च करते हैं, मैं उम्मीद प्रतिक्रियाओं मिलता है। फिर मैं अपने ऐप को मारता हूं, वाईफाई अक्षम करता हूं और ऐप को फिर से लॉन्च करता हूं। मैं इस पल में कैश डेटा की सेवा करने की उम्मीद करता हूं। लेकिन यह विफल रहता है और मैं केवल लॉग में मुद्रित लाइनों OkHttp देख सकते हैं:

HTTP विफल: java.net.UnknownHostException: मेजबान को हल करने "my-domain.com" में असमर्थ: नहीं पता होस्ट नाम के साथ जुड़े

अंतिम बात, RFC 2616 में, एक पढ़ सकते हैं:

अधिकतम-बासी: यह दर्शाता है कि ग्राहक एक प्रतिक्रिया कि इसकी समाप्ति समय पार कर गया है स्वीकार करने को तैयार है। यदि अधिकतम-स्टेल को मान असाइन किया गया है, तो ग्राहक की प्रतिक्रिया को स्वीकार करने के लिए तैयार है, जिसने सेकेंड की निर्दिष्ट संख्या से अधिक समय तक इसकी समाप्ति समय पार कर ली है। यदि अधिकतम-स्टेल को कोई मान निर्दिष्ट नहीं किया गया है, तो ग्राहक किसी भी आयु की पुरानी प्रतिक्रिया स्वीकार करने के इच्छुक है।

जब मैं कोई मान निर्दिष्ट नहीं करता हूं, तो यह वास्तव में काम करता है (वाईफ़ाई नीचे होने पर भी मुझे प्रतिक्रिया मिलती है)। अभी के लिए यह एकमात्र तरीका है जिसे मैंने इसे "काम" करने के लिए पाया। तो शायद मैं सिर्फ कैश-नियंत्रण निर्देश को गलत समझ सकता हूं!

इस बिंदु पर मैं वास्तव में उलझन में हूं। मैं वास्तव में OkHttp कैश सिस्टम का उपयोग करने में सक्षम होना चाहता हूं, लेकिन किसी भी तरह से मुझे कुछ याद आ रहा है।

उस पाठ को पढ़ने के लिए धन्यवाद!

उत्तर

0

उपयोग इस विधि पुनः स्थापित करने के लिए

OkHttpClient okHttpClient = createCachedClient(MainActivity.this); 
Retrofit retrofit=new Retrofit.Builder() 
     .client(okHttpClient) 
     .baseUrl(API) 
     .addConverterFactory(GsonConverterFactory 
     .create()).build(); 

जोड़े इस अनुमति को प्रकट करने okkhttpclient कैश की गई इस ग्राहक जोड़ने OkHttpClient बनाने के लिए

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 com.squareup.okhttp.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(); 
         com.squareup.okhttp.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 com.squareup.okhttp.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(); 
         com.squareup.okhttp.Response response = chain.proceed(request); 
         return response.newBuilder() 
           .removeHeader("Pragma") 
           .removeHeader("Cache-Control") 
           .header("Cache-Control", cacheHeaderValue) 
           .build(); 
        } 
       } 
     ); 
     return okHttpClient; 
    } 

    private boolean isOnline(Context context) { 
     ConnectivityManager connectivity = (ConnectivityManager) _context.getSystemService(Context.CONNECTIVITY_SERVICE); 
     if (connectivity != null) { 
      NetworkInfo[] info = connectivity.getAllNetworkInfo(); 
      if (info != null) 
       for (int i = 0; i < info.length; i++) 
        if (info[i].getState() == NetworkInfo.State.CONNECTED) { 
         return true; 
        } 
     } 
     return false; 


     } 

कॉल createCachedClient() विधि बनाने के लिए

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> 

यदि इंटरनेट पहली बार उपलब्ध है तो यह सेवा और कैश को कॉल करेगा अनुरोध, अगली बार 2419200 मिलीसेकंड तक यह प्रतिक्रिया देने के लिए कैश का उपयोग करेगा। अगर ऑफलाइन होने पर डिवाइस 2419200 मिलीसेकंड तक सर्वर पर नहीं पहुंच जाएगा।

+0

उत्तर के लिए धन्यवाद, लेकिन मैं वर्तमान नेटवर्क स्थिति से कोई फर्क नहीं पड़ता, कैश की जांच करने के लिए रेट्रोफिट चाहूंगा। रेट्रोफिट को पहले कैश को हमेशा जांचना चाहिए, और इसकी सामग्री को अभी भी वैध होने पर वापस कर देना चाहिए। या बस सामग्री लाने की कोशिश करें, चाहे नेटवर्क स्थिति चाहे (क्योंकि मुझे लगता है कि विफलता के मामले में परिणाम कैश नहीं किया गया है)। – Gordak

+0

यह समीकरण करेगा। केवल पहली बार यह सर्वर पर हिट करेगा जब हर बार यह कैश की जांच करेगा। –

+0

क्या आपको कोई समाधान मिला? मेरे पास एक ही त्रुटि है 'अज्ञातहोस्ट अपवाद: मेजबान को हल करने में असमर्थ' लेकिन ऐसा लगता है कि यह त्रुटि कैश के कारण दिखाई देती है: मुझे यह त्रुटि है 'हटाएं विफल: ENOENT (ऐसी कोई फ़ाइल या निर्देशिका नहीं):/data/user/0/com.myapp/cache/cache_file/journal.tmp' अज्ञातहोस्ट अपवाद से ठीक पहले। – Bogy

संबंधित मुद्दे