2017-07-29 33 views
1

我连接到webService像波纹管:Retrofit 2 + rx - 在android中如何检查响应来源(网络,缓存或两者)?

private CompositeDisposable mCompositeDisposable; 
PublicApi publicApi = retrofitApi.getClient("https://xxx.xxx.xxx", context, 1); 
     mCompositeDisposable.add(publicApi.language("getLanguages") 
       .observeOn(AndroidSchedulers.mainThread()) 
       .subscribeOn(Schedulers.io()) 
       .subscribe(language -> responseLanguage(language, resultListener), language -> errorLanguage(language, resultListener))); 

而得到的结果类似波纹管:

private void responseLanguage(Languages languages, RemoteDataSource.ResultListener<Languages> resultListener) { 
} 

private void errorLanguage(Throwable error, RemoteDataSource.ResultListener<Languages> resultListener) { 
    error.printStackTrace(); 
} 

我如何检查响应起源像波纹管链接:

Retrofit 2 — Check Response Origin (Network, Cache, or Both)

我需要知道结果来自缓存或web服务(在线),因为我正在缓存结果li柯波纹管:

public class RetrofitApi { 
    private static PublicApi retrofit = null; 
    private Context context; 


    public PublicApi getClient(String url, Context context, Integer value) { 
     OkHttpClient okHttpClient; 
     this.context = context; 
     try { 
      // Create a trust manager that does not validate certificate chains 
      final TrustManager[] trustAllCerts = new TrustManager[]{ 
        new X509TrustManager() { 
         @Override 
         public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException { 
         } 

         @Override 
         public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException { 
         } 

         @Override 
         public java.security.cert.X509Certificate[] getAcceptedIssuers() { 
          return new java.security.cert.X509Certificate[]{}; 
         } 
        } 
      }; 

      // Install the all-trusting trust manager 
      final SSLContext sslContext = SSLContext.getInstance("SSL"); 
      sslContext.init(null, trustAllCerts, new java.security.SecureRandom()); 
      // Create an ssl socket factory with our all-trusting manager 
      final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory(); 
      OkHttpClient.Builder builder = new OkHttpClient.Builder(); 
      builder.sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0]); 
      builder.hostnameVerifier(new HostnameVerifier() { 
       @Override 
       public boolean verify(String hostname, SSLSession session) { 
        return true; 
       } 
      }); 

      if (value == 1) { 
       //For get Log see D/OkHttp 
       HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); 
       // set your desired log level 
       logging.setLevel(HttpLoggingInterceptor.Level.HEADERS); 
       File httpCacheDirectory = new File(this.context.getCacheDir(), "responses"); 
       int cacheSize = 10 * 1024 * 1024; // 10 MiB 
       Cache cache = new Cache(httpCacheDirectory, cacheSize); 

       if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { 
        okHttpClient = builder. 
          addNetworkInterceptor(REWRITE_RESPONSE_INTERCEPTOR) 
          .addInterceptor(OFFLINE_INTERCEPTOR) 
          .addInterceptor(logging) 
          .cache(cache) 
          .build(); 
       } else { 
        okHttpClient = new OkHttpClient.Builder() 
          .addNetworkInterceptor(REWRITE_RESPONSE_INTERCEPTOR) 
          .addInterceptor(OFFLINE_INTERCEPTOR) 
          .addInterceptor(logging) 
          .cache(cache) 
          .build(); 
       } 


      } else { 
       okHttpClient = builder.build(); 
      } 
     } catch (Exception e) { 
      throw new RuntimeException(e); 
     } 


     retrofit = new Retrofit.Builder() 
       .baseUrl(url) 
       .client(okHttpClient) 
       //.client(httpClient.build()) 
       .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) 
       .addConverterFactory(GsonConverterFactory.create()) 
       .build().create(PublicApi.class); 

     return retrofit; 
    } 

    private 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() 
        .removeHeader("Pragma") 
        .header("Cache-Control", "public, max-age=" + 60) 
        .build(); 
     } else { 
      return originalResponse; 
     } 
    }; 


    private Interceptor OFFLINE_INTERCEPTOR = chain -> { 
     Request request = chain.request(); 
     if (!Utils.isNetworkAvailable(context)) { 
      int maxStale = 60 * 60 * 24 * 2; // tolerate 2-days stale 
      request = request.newBuilder() 
        .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale) 
        .build(); 
     } 

     return chain.proceed(request); 
    }; 
} 
+0

我有像你一样的问题,并有相同的代码,你有没有找到解决方案呢? –

回答

1

您可以在PublicApi接口改造的Response对象,使用RxJava时RxJavaCallAdapaterFactory包装你的预期目标:

@GET 
Response<Languages> language(String param); 

Response是围绕一个包含各种信息的请求响应的包装回应,这是您提及的article中的同一个对象,即在使用Call<>时,在非RxJava enqueue()请求中返回。
然后在订户中,您将获得一个Response<Languages>对象,并且您将能够使用response.raw().cacheResponse()/response.raw().networkResponse()来检查它是否为缓存对象,如上述教程中所述。