2017-01-10 123 views
2

我想從我的公司API緩存HTTP響應,但它看起來像應用程序不能訪問緩存目錄緩存錯誤:與改造2和3 okhttp

W/System.err的:刪除失敗: ENOENT(沒有這樣的文件或目錄): /data/user/0/com.appname/cache/cache_file/journal.tmp

W/System.err的: 的java.net.UnknownHostException:無法解析主機 「www.domain.com」:沒有與主機名關聯的地址

我按照這個tutorial。下面是我安裝改造(2.1.0):

import lu.CompanyName.R; 
import lu.CompanyName.interfaces.CompanyNameAPI; 
import okhttp3.Cache; 
import okhttp3.Interceptor; 
import okhttp3.OkHttpClient; 
import okhttp3.Request; 
import okhttp3.Response; 
import okhttp3.logging.HttpLoggingInterceptor; 
import retrofit2.Retrofit; 
import retrofit2.converter.gson.GsonConverterFactory; 

import static okhttp3.logging.HttpLoggingInterceptor.Level.HEADERS; 


public class Injector { 

    private static final String CACHE_CONTROL = "Cache-Control"; 

    private static Retrofit provideRetrofit (String baseUrl) { 
     return new Retrofit.Builder() 
       .baseUrl(baseUrl) 
       .client(provideOkHttpClient()) 
       .addConverterFactory(GsonConverterFactory.create()) 
       .build(); 
    } 

    private static OkHttpClient provideOkHttpClient() { 
     return new OkHttpClient.Builder() 
       .addInterceptor(provideHttpLoggingInterceptor()) 
       .addInterceptor(provideOfflineCacheInterceptor()) 
       .addNetworkInterceptor(provideCacheInterceptor()) 
       .cache(provideCache()) 
       .build(); 
    } 

    private static Cache provideCache() { 
     /* 
     Cache cache = null; 
     try 
     { 
      File dir = CompanyName.getInstance().getExternalCacheDir(); 

      if (dir == null) 
       dir = CompanyName.getInstance().getCacheDir(); 

      if (dir == null) 
       Log.e("provideCache", "dir is null"); 

      cache = new Cache(new File(dir, "http-cache"), 10 * 1024 * 1024); // 10 MB 

      if (cache == null) 
       Log.e("provideCache", "cache is null"); 

     } 
     catch (Exception e) 
     { 
      Log.e("provideCache", "Could not create Cache!"); 
     } 
     return cache;*/ 

     /* 
     File httpCacheDirectory = new File(CompanyName.getInstance().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("provideCache", "URLs in cacheHttpClient : "); 
      while (iterator.hasNext()) { 
       Log.i("provideCache", iterator.next()); 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
      Log.i("provideCache", "CACHE NOT INIT"); 
     } 
     return cache;*/ 

     return new Cache(new File(CompanyName.getInstance().getCacheDir(), "cache_file"), 20 * 1024 * 1024); 
    } 

    private static HttpLoggingInterceptor provideHttpLoggingInterceptor() { 
     HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(); 
     httpLoggingInterceptor.setLevel(HEADERS); 
     return httpLoggingInterceptor; 
    } 

    private static Interceptor provideCacheInterceptor() { 
     /*return new Interceptor() { 
      @Override 
      public Response intercept (Chain chain) throws IOException { 
       Response response = chain.proceed(chain.request()); 

       // re-write response header to force use of cache 
       CacheControl cacheControl = new CacheControl.Builder() 
         .maxAge(2, TimeUnit.HOURS) 
         .build(); 

       return response.newBuilder() 
         .header(CACHE_CONTROL, cacheControl.toString()) 
         .build(); 
      } 
     };*/ 
     return new Interceptor() { 
      @Override 
      public Response intercept(Chain chain) throws IOException { 
       Request originalRequest = chain.request(); 
       String cacheHeaderValue = CompanyName.getInstance().checkIfHasNetwork() 
         ? "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(); 
      } 
     }; 
    } 

    private static Interceptor provideOfflineCacheInterceptor() { 
     /*return new Interceptor() 
     { 
      @Override 
      public Response intercept (Chain chain) throws IOException 
      { 
       Request request = chain.request(); 

       if (!CompanyName.hasNetwork()) 
       { 
        CacheControl cacheControl = new CacheControl.Builder() 
          //.maxStale(7, TimeUnit.DAYS) 
          .build(); 

        request = request.newBuilder() 
          .cacheControl(cacheControl) 
          .build(); 
       } 

       return chain.proceed(request); 
      } 
     };*/ 
     return new Interceptor() { 
      @Override 
      public Response intercept(Chain chain) throws IOException { 
       Request originalRequest = chain.request(); 
       String cacheHeaderValue = CompanyName.getInstance().checkIfHasNetwork() 
         ? "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(); 
      } 
     }; 
    } 

    public static CompanyNameAPI provideCompanyNameAPI() { 
     return provideRetrofit(CompanyName.getInstance().getString(R.string.base_url)).create(CompanyNameAPI.class); 
    } 
} 

我試圖找到在互聯網和計算器的一些解決方案(仍然在上面的代碼註釋),因爲起初我以爲這是一個「緩存控制」重寫問題。

我還向清單添加了權限READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE,但它不會更改任何內容。

我錯過了什麼嗎? (我正在使用Android 6.0.1 API 23在三星進行測試)

回答

0

您可能缺少清單中的INTERNET權限。

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

這對於越來越UnknownHostException錯誤的一個常見原因。

或者,通過在瀏覽器中訪問該網站,確保您可以實際訪問該設備上的該網站

+1

不,我已經添加了此權限。事實上,只有當我關閉互聯網連接(飛行模式)時,我纔得到上述錯誤:我的測試包括首次獲取數據(互聯網)以獲取緩存,然後從緩存中獲取數據(互聯網關閉)。 – Bogy

0

關於第一個錯誤,讓我們來看看提供OkHttpClient緩存目錄:

private static OkHttpClient provideOkHttpClient() { 
    return new OkHttpClient.Builder() 
      .addInterceptor(provideHttpLoggingInterceptor()) 
      .addInterceptor(provideOfflineCacheInterceptor()) 
      .addNetworkInterceptor(provideCacheInterceptor()) 
      .cache(provideCache()) 
      .build(); 
} 

您已經使用了相同的緩存目錄許多OkHttpClient,很多情況下可以踩對方,破壞響應緩存。 要解決這個問題,你可以使用OkHttpClient一次,配置它的緩存,並在任何地方使用同一個實例。您可以嘗試如下:

private static Retrofit provideRetrofit (String baseUrl) { 
    return new Retrofit.Builder() 
      .baseUrl(baseUrl) 
      .client(okHttpClient) 
      .addConverterFactory(GsonConverterFactory.create()) 
      .build(); 
} 

private static OkHttpClient okHttpClient = new OkHttpClient.Builder() 
      .addInterceptor(provideHttpLoggingInterceptor()) 
      .addInterceptor(provideOfflineCacheInterceptor()) 
      .addNetworkInterceptor(provideCacheInterceptor()) 
      .cache(provideCache()) 
      .build(); 

有關緩存,OkHttpClient更多信息,你可以在this link看一看。