2016-08-08 6 views
0

Я действительно пытаюсь использовать Retrofit с RxJava/RxAndroid. Я сделал это, используя обычный метод Retrofit2 Callback в предыдущем приложении без использования Reactive Programming, и он отлично работал. Итак, вот оно. Мне нужно, чтобы Tail Recall функция, предназначенная для извлечения всего Local Government с сервера. В поле API используется разбиение на страницы (I have to construct the URL with ?page=1, perPage=2). Я должен сделать это, пока не получу все данные. Итак, ниже мой Rx кодRetrofit2 Рекурсия хвоста с использованием RxJava/RxAndroid

public static Observable<LgaListResponse> getPages(Context acontext) { 
    String token = PrefUtils.getToken(acontext); 
    BehaviorSubject<Integer> pageControl = BehaviorSubject.<Integer>create(1); 
    Observable<LgaListResponse> ret2 = pageControl.asObservable().concatMap(integer -> { 
     if (integer > 0) { 
      Log.e(TAG, "Integer: " + integer); 
      return ServiceGenerator.createService(ApiService.class, token) 
        .getLgas(String.valueOf(integer), String.valueOf(21)) 
        .doOnNext(lgaListResponse -> { 
         if (lgaListResponse.getMeta().getPage() != lgaListResponse.getMeta().getPageCount()) { 
          pageControl.onNext(initialPage + 1); 
         } else { 
          pageControl.onNext(-1); 
         } 
        }); 
     } else { 
      return Observable.<LgaListResponse>empty().doOnCompleted(pageControl::onCompleted); 
     } 
    }); 

    return Observable.defer(() -> ret2); 
} 

И мой ServiceGenerator Класс

public class ServiceGenerator { 

     private static final String TAG = "ServiceGen"; 
     private static OkHttpClient.Builder builder = new OkHttpClient.Builder(); 

     private static Retrofit.Builder retrofitBuilder = 
       new Retrofit.Builder() 
         .baseUrl(BuildConfig.HOST) 
         .addCallAdapterFactory(RxJavaCallAdapterFactory.createWithScheduler(Schedulers.io())) 
         .addConverterFactory(GsonConverterFactory.create(CustomGsonParser.returnCustomParser())); 

     public static <S> S createService(Class<S> serviceClass, String token) { 

      builder.addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)); 
      /*builder.addNetworkInterceptor(new StethoInterceptor());*/ 
      builder.connectTimeout(30000, TimeUnit.SECONDS); 
      builder.readTimeout(30000, TimeUnit.SECONDS); 
      if (token != null) { 
       Interceptor interceptor = chain -> { 
        Request newRequest = chain.request().newBuilder() 
          .addHeader("x-mobile", "true") 
          .addHeader("Authorization", "Bearer " + token).build(); 
        return chain.proceed(newRequest); 
       }; 
       builder.addInterceptor(interceptor); 
      } 
      OkHttpClient client = builder.build(); 

      Retrofit retrofit = retrofitBuilder.client(client).build(); 
      Log.e(TAG, retrofit.baseUrl().toString()); 
      return retrofit.create(serviceClass); 
     } 

     public static Retrofit retrofit() { 
      OkHttpClient client = builder.build(); 
      return retrofitBuilder.client(client).build(); 
     } 

     public static class CustomGsonParser { 

      public static Gson returnCustomParser(){ 
       return new GsonBuilder() 
         .setExclusionStrategies(new ExclusionStrategy() { 
          @Override 
          public boolean shouldSkipField(FieldAttributes f) { 
           return f.getDeclaringClass().equals(RealmObject.class); 
          } 

          @Override 
          public boolean shouldSkipClass(Class<?> clazz) { 
           return false; 
          } 
         }) 
         .create(); 
      } 
     } 
    } 

Итак, я заметил на первый звонок, я получаю ответ, но на втором, то 440Error выбрасывается. URL-адрес сформирован, но запрос выдает 400Error. Я не знаю, почему это бросает 400 все работает нормально, если я использую POSTMAN для тестирования. И я тоже тестировал свой старый код. Log слишком длинный, поэтому я положил его в pastebinLOGS любую благодарность за помощь. Я написал большую часть этого приложения с RxAndroid/RxJava. Спасибо

+0

Ну, во-первых, рекурсия - это не лучший способ разбиения на страницы с использованием RxJava и дооснастки. См. Один из ответов на [этот вопрос] (http://stackoverflow.com/questions/37326380/paginate-observable-results-without-recursion-rxjava) для лучшего способа. Во-вторых, где вы подписываетесь на наблюдаемые? Кажется, у вас есть несколько подписей, которые все инициируют новые запросы, поскольку наблюдаемый вами генератор «холодный». – JohnWowUs

+0

Я считаю, что эта строка '.subscribe (новый подписчик () {' предназначен для того, чтобы подписаться на 'onComplete',' onError' и 'onNext' правильно? И эти' (clientBus.hasObservers()) '' clientBus 'is singleton.Таким образом, он не генерируется несколько раз. И просто отправить сообщение в UI –

+0

Да, но в какой-то момент вы вызываете создание LgaHandler с помощью' getInstance ', а затем вызываете 'getLgas', не так ли? вы вызываете это несколько раз? – JohnWowUs

ответ

1

Я предлагаю вам упростить вещи (и удалить рекурсию). Сначала создайте свои страницы, используя что-то вроде

public static Observable<LgaListResponse> getPages(Context acontext, int initialPage, int perPage) { 
    String token = PrefUtils.getToken(acontext); 
    BehaviorSubject<Integer> pagecontrol = BehaviorSubject.<Integer>create(initialPage); 
    Observable<LgaListResponse> ret2 = pagecontrol.asObservable().concatMap(
     new Func1<Integer,Observable<LgaListResponse>>() { 
      Observable<LgaListResponse> call(Integer pageNumber) { 
       if (pageNumber > 0) { 
        return ServiceGenerator.createService(ApiService.class, token) 
              .getLgas(String.valueOf(aKey), String.valueOf(perPage)) 
              .doOnNext(
               new Action1<LgaListResponse>() { 
                void call(LgaListResponse page) { 
                 if (page.getMeta().getPage() != page.getMeta().getPageCount()) { 
                  pagecontrol.onNext(page.getMeta().getNextPage()); 
                 } else { 
                  pagecontrol.onNext(-1); 
                 }   
                } 
               } 
              ); 
       }            
       else { 
        return Observable.<LgaListResponse>empty().doOnCompleted(()->pagecontrol.onCompleted()); 
       }   
      } 
     } 
    ); 

    return Observable.defer(
       new Func0<Observable<LgaListResponse>() { 
        Observable<LgaListResponse> call() { 
         return ret2; 
        } 
       } 
      );    
} 

затем подпишитесь на полученный наблюдаемый. Это выглядит ужасно, потому что я избегал использования лямбда, но он должен работать.

+0

Я очень благодарен за помощь. Но, я все еще испытываю ту же ошибку. Я думаю, что причиной этого является генератор обслуживания. Я отредактировал свой вопрос –

+0

Я думаю, что, возможно, вам следует создать службу один раз и повторно использовать ее вместо создания службы для каждой новой страницы. – JohnWowUs

Смежные вопросы