2015-12-21 274 views
3

所以目前,林制作带有日期参数一个异步网络请求(使用改造),并且如果与该原位缺口200的响应代码,请求返回(或者如果它的429,400,或如果响应正文是空的,无论哪个最容易确定),我在1天前用日期参数发出一个新的请求。同样,如果这一请求回来了原位缺口200的响应代码,我做一个日期比之前的早1天,共计3个可能的请求如果前两个失败多了一个请求。改造及RxJava,避免回调地狱

我目前正在与一群回调的实现这一目标,并呼吁建立与-1为每个尝试一天执行请求的新方法。

我知道我可以实现与Rx和内置的Rx功能改造探索一个清晰的解决方案。这将如何完成?

+0

什么改装版本? –

+0

@NikoYuwono 2.0.0-β2 – Orbit

+0

检查我的答案 –

回答

1

首先,你需要在你的依赖

compile 'com.squareup.retrofit:adapter-rxjava:2.0.0-beta2' 
compile 'io.reactivex:rxandroid:1.0.1' 

,然后添加RxAndroid和RxJava适配器需要电话适配器注册到改造声明

Retrofit retrofit = new Retrofit.Builder() 
     .baseUrl(myBaseurl) 
     .addConverterFactory(GsonConverterFactory.create()) 
     .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 
     .build(); 

然后你就可以改变你的服务接口返回类型从呼叫到可观察

public interface MyAPIService { 

    @POST("user") 
    Call<User> getUser(); 

    @POST("user") 
    Observable<Response<User>> getUserWithRxJava(); 

    @POST("user_friends") 
    Observable<Response<List<User>>> getUserFriends(); 
} 

并且t他是链接调用

myService.getUserWithRxJava() 
    .observeOn(AndroidSchedulers.mainThread()) 
    .flatMap(new Func1<Response<User>, Observable<Response<List<User>>>>() { 
     @Override 
     public Observable<List<Home>> call(Response<User> responseUser) { 
      // You can also use responseUser.code to get the response code 
      // but isSuccess() function will return true if the code 
      // is in the range [200..300) 
      if (responseUser.isSuccess()) { 
       return myService.getUserFriends(); 
      } else { 
       // You can also use Observable.empty() if you want to ignore unsuccessful response 
       return Observable.error(myThrowable); 
      } 
     } 
    }) 
    .subscribe(new Subscriber<Response<List<User>>>() { 
     @Override 
     public void onCompleted() { 
      // TODO Completed 
     } 

     @Override 
     public void onError(Throwable e) { 
      // TODO Handle the error 
     } 

     @Override 
     public void onNext(Response<List<User>> friendListResponse) { 
      // TODO do something with the data 
      // To get the serialized data you can use friendListResponse.body(); 
     } 
    }); 
1

非200的响应应该回来为RetrofitError对象,其中包含Response对象的状态代码的例子。

你可以做这样的事情:

observable 
    .retryWhen(new RetryStrategy()) 
    .subscribe(...); 

RetryStrategy可能是这样的(注意,我用retrolambda,所以无论你看到->只是一个新的匿名内部类替换):

public class RetryStrategy implements Func1<Observable<? extends Throwable>, Observable<?>> { 

    public RetryStrategy() {} 

    @Override 
    public Observable<?> call(Observable<? extends Throwable> attempts) { 
     return attempts.flatMap((throwable) -> { 
      if (throwable instanceof RetrofitError) { 
       RetrofitError error = (RetrofitError) throwable; 
       if (error.getKind() == RetrofitError.Kind.HTTP) { 
        if (error.getResponse().getStatus() == 401) { 

         // This is where you attempt to recover 
         return someRecoveryObservable???; 
        } 
       } 
      } 

      // Bubble any other errors back up, e.g. connection loss. 
      return Observable.error(throwable); 
     }); 
    } 
} 

你也可以实现Exponential Backoff这里加入支持重试次数,在你的恢复阶段使用Observable.timer(long, TimeUnit)沿(和计算基础上尝试的当前数量的时间)。 Spotty连接问题有时会从这种方法中大大受益 - 尤其是在火灾后遗症中忘记执行的任务。