2017-02-15 50 views
0

我试图执行离线兑现时互联网连接丢失,以便我可以显示缓存中的数据。这是我迄今为止所做的。 我的问题是如何让我的observable返回缓存的数据列表,而不仅仅是返回错误? 我的服务发电机:缓存与改进2.0和rxjava 2与okhttp3

public class ServiceGenerator { 

public static final String API_BASE_URL = UrlManager.BASE_URL_API; 
private static final String CACHE_CONTROL = "Cache-Control"; 



private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder() 
     .connectTimeout(60, TimeUnit.SECONDS) 
     .writeTimeout(60,TimeUnit.SECONDS) 
     .readTimeout(60,TimeUnit.SECONDS); 

private static Gson gson = new GsonBuilder() 

private static Retrofit.Builder builder = 
     new Retrofit.Builder() 
       .baseUrl(API_BASE_URL) 
       .addConverterFactory(GsonConverterFactory.create(gson)) 
       .addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io())); 
private static Retrofit retrofit; 

public static Gson getGson() { 
    return gson; 
} 

public static void setup() { 

    httpClient.addInterceptor(provideOfflineCacheInterceptor()); 
    httpClient.addInterceptor(new AddCookiesInterceptor()); // VERY VERY IMPORTANT 
    httpClient.addInterceptor(new ReceivedCookiesInterceptor()); // VERY VERY IMPORTANT 
    httpClient.addInterceptor(provideHttpLoggingInterceptor()); 
    httpClient.addNetworkInterceptor(new StethoInterceptor());// Stetho 
    httpClient.addNetworkInterceptor(provideCacheInterceptor()); 
    httpClient.cache(provideCache()); 
    OkHttpClient client = httpClient.build(); 
    retrofit = builder.client(client).build(); 
} 

public static <S> S createService(Class<S> serviceClass) { 
    return createService(serviceClass, null); 
} 

public static <S> S createService(Class<S> serviceClass, final String authToken) { 
    if (authToken != null) { 
     httpClient.addInterceptor(new Interceptor() { 
      @Override 
      public Response intercept(Chain chain) throws IOException { 
       Request original = chain.request(); 

       // Request customization: add request headers 
       Request.Builder requestBuilder = original.newBuilder() 
         .header("Authorization", authToken) 
         .method(original.method(), original.body()); 

       Request request = requestBuilder.build(); 
       return chain.proceed(request); 
      } 
     }); 
    } 


    return retrofit.create(serviceClass); 
} 

public 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.MINUTES) 
        .build(); 

      return response.newBuilder() 
        .header(CACHE_CONTROL, cacheControl.toString()) 
        .build(); 
     } 
    }; 
} 

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

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

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

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

private static Cache provideCache() { 
    Cache cache = null; 
    try { 
     cache = new Cache(new File(UruzApplication.getInstance().getCacheDir(), "http-cache"), 
       10 * 1024 * 1024); // 10 MB 
    } catch (Exception e) { 
     Timber.e(e, "Could not create Cache!"); 
    } 
    return cache; 
} 
private static HttpLoggingInterceptor provideHttpLoggingInterceptor() 
{ 
    HttpLoggingInterceptor httpLoggingInterceptor = 
      new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() 
      { 
       @Override 
       public void log (String message) 
       { 
        Timber.d(message); 
       } 
      }); 
    httpLoggingInterceptor.setLevel(true ? HEADERS : NONE); 
    return httpLoggingInterceptor; 
} 

}

我的观察:

public static Observable<List<WeekDietPlan>> 
fetchPackageWeeksDaysDietPlan(int traineeId) { 

    DietService requestService = ServiceGenerator.createService(DietService.class); 
    return requestService.getPackageWeekDaysDietPlan(UrlManager.getTraineeDietPackageDetailsUrl(), 
      traineeId) 
      .flatMap(new Function<JsonElement, Observable<List<WeekDietPlan>>>() { 
       @Override 
       public Observable<List<WeekDietPlan>> apply(JsonElement jsonElement) throws Exception { 
        JsonObject asJsonObject = jsonElement.getAsJsonObject(); 
        String result = asJsonObject.get(UrlManager.ResultTypes.RESULT).getAsString(); 

        Timber.d(TAG, "result Tag" + result); 

        if (UrlManager.ResultTypes.isError(result) || UrlManager.ResultTypes.isFailure(result)) { 
         String errorMessage = asJsonObject.get(UrlManager.ResultTypes.RESULT_ERROR_MESSAGE).getAsString(); 
         return Observable.error(new Exception(errorMessage)); 
        } 


        if (UrlManager.ResultTypes.isSucess(result)) { 


         if (!GsonHelper.isNull(asJsonObject.get(UrlManager.ResultTypes.RESULT_DATA)) && asJsonObject.get(UrlManager.ResultTypes.RESULT_DATA).isJsonArray()) { 
          return Observable.just(WeekDietPlan.PackageDietWeekDaysListParser.fromJsonElement(asJsonObject.getAsJsonArray(UrlManager.ResultTypes.RESULT_DATA))); 
         } else { 
          return Observable.error(new Exception("Data is empty")); 
         } 


        } 

        if (UrlManager.ResultTypes.isLogin(result)) { 
         return Observable.error(new SessionTimeoutException()); 
        } 


        return Observable.error(new Exception("Unkown Tag")); 
       } 
      }) 
      .observeOn(AndroidSchedulers.mainThread()); 

} 

我的API调用:

private void retrievePackageWeekDaysPlan() { 
    hideConnectionErrorLayout(); 
    if (!swipRefreshLayout_reLoad.isRefreshing()) { 
     swipRefreshLayout_reLoad.setRefreshing(true); 
    } 

    DietNetworkCall.fetchPackageWeeksDaysDietPlan(1).subscribe(new Observer<List<WeekDietPlan>>() { 
     @Override 
     public void onSubscribe(Disposable d) { 
      Timber.d(TAG, "onSubscribe() called with: d = [" + d + "]"); 
      compositeSubscription.add(d); 
     } 

     @Override 
     public void onNext(List<WeekDietPlan> list) { 
      Timber.d(TAG, "onNext() called with: value = [" + list.size() + "]"); 
      swipRefreshLayout_reLoad.setRefreshing(false); 

      hideConnectionErrorLayout(); 

      if (list.size() == 0) 
      { 
       Toast.makeText(getContext(), R.string.noDietPackageAvailable, Toast.LENGTH_SHORT).show(); 
      } 

      bindRecyclerData(list); 


     } 

     @Override 
     public void onError(Throwable e) { 
      e.printStackTrace(); 
      Timber.d(TAG, "onError() called with: e = [" + e + "]"); 

      swipRefreshLayout_reLoad.setRefreshing(false); 
      if (e instanceof IOException) { 
       Toast.makeText(getContext(), R.string.connectionError, Toast.LENGTH_SHORT).show(); 


      } else if (e instanceof NullPointerException) { 

      } else if (e instanceof SessionTimeoutException) { 
       AuthenticationManager.logOut(); 

      } else { 
       Toast.makeText(getContext(), 
         e.getMessage(), 
         Toast.LENGTH_SHORT).show(); 
      } 
     } 

     @Override 
     public void onComplete() { 
      Log.d(TAG, "onComplete() called"); 
     } 
    }); 


} 

回答

0

要返回缓存中的数据错误,你可以使用onErrorReturn运算符即:

Instructs an Observable to emit an item (returned by a specified function) rather than invoking onError if it encounters an error.

不同的运营商的列表上的错误恢复:https://github.com/ReactiveX/RxJava/wiki/Error-Handling-Operators

+0

是啊,但我怎么能返回缓存数据。 –

+0

'onErrorReturn'作为一个函数在出现错误时调用的函数;该函数返回的项目将通过'Observable'而不是错误传播。这个操作符可以用你定义的有效响应来替换错误,在你的情况下你的缓存数据。 –

+0

兄弟我完全理解这部分,我想要的是如何从改造中获得缓存数据。 –