Я пытаюсь сделать запрос, который извлекает данные с сервера до тех пор, пока это не потянет данные. Проблема в том, что ответ имеет 21Data perPage. Но есть метатег, чтобы узнать, есть ли следующая страница. Итак, я могу тянуть до nextPage == totalPage
.Repeat A Retrofit Observable Request
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();
}
}
}
Мой запрос Журналы
E/ServiceGen: http://theUrl.net/
D/OkHttp: --> GET http://theUrl.net/lga?page=1&per_page=21 http/1.1
D/OkHttp: x-mobile: true
D/OkHttp: --> END GET
D/OkHttp: --> GET http://theUrl.net/lga?page=1&per_page=21 http/1.1
D/OkHttp: x-mobile: true
D/OkHttp: --> END GET
D/OkHttp: <-- 200 OK http://theUrl.net/lga?page=1&per_page=21 (929ms)
D/OkHttp: Date: Wed, 10 Aug 2016 09:01:00 GMT
D/OkHttp: Content-Type: application/json; charset=utf-8
D/OkHttp: <-- 200 OK http://theUrl.net/lga?page=1&per_page=21 (933ms)
D/OkHttp: Date: Wed, 10 Aug 2016 09:01:00 GMT
D/OkHttp: Content-Type: application/json; charset=utf-8
D/OkHttp: --> GET http://theUrl.net/lga?page=2&per_page=21 http/1.1
D/OkHttp: --> END GET
D/OkHttp: --> GET http://theUrl.net/lga?page=2&per_page=21 http/1.1
D/OkHttp: --> END GET
D/OkHttp: --> GET http://theUrl.net/lga?page=2&per_page=21 http/1.1
D/OkHttp: --> END GET
D/OkHttp: <-- 400 Bad Request http://theUrl.net/lga?page=2&per_page=21 (695ms)
D/OkHttp: <-- END HTTP (177-byte body)
D/OkHttp: <-- 400 Bad Request http://theUrl.net/lga?page=2&per_page=21 (696ms)
D/OkHttp: <-- END HTTP (177-byte body)
D/OkHttp: <-- 400 Bad Request http://theUrl.net/lga?page=2&per_page=21 (696ms)
Если вы заметили http://theUrl.net/lga?page=1&per_page=21
называли дважды и http://theUrl.net/lga?page=3&per_page=21
был назван в 3 раза.
Итак, я решил использовать свой старый файл RestClient Class
. И все получилось отлично. Но нет ничего плохого. Он запросил весь запрос до последнего. Я до сих пор не могу найти то, что случилось с моим ServiceGenerator class
RestClient класса File
public class RestClient {
private static final String TAG = "RestClient";
private static ApiService apiEndpointInterface;
private static Context context;
/*static {
setupRestClient();
}*/
public static ApiService get(Context cont) {
context = cont;
if (apiEndpointInterface != null)
return apiEndpointInterface;
setupRestClient();
return apiEndpointInterface;
}
private static void setupRestClient() {
// Define the interceptor, add authentication headers
Interceptor interceptor = chain -> {
Request newRequest = chain.request().newBuilder()
/*.addHeader("x-mobile", "true")*/
.addHeader("Authorization", "Bearer " + PrefUtils.getToken(context)).build();
return chain.proceed(newRequest);
};
// Add the interceptor to OkHttpClient
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.interceptors().add(interceptor);
builder.addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY));
builder.addNetworkInterceptor(new StethoInterceptor());
builder.connectTimeout(30000, TimeUnit.SECONDS);
builder.readTimeout(30000, TimeUnit.SECONDS);
OkHttpClient client = builder.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BuildConfig.HOST)
.addCallAdapterFactory(RxJavaCallAdapterFactory.createWithScheduler(Schedulers.io()))
.addConverterFactory(GsonConverterFactory.create(CustomGsonParser.returnCustomParser()))
.client(client)
.build();
apiEndpointInterface = retrofit.create(ApiService.class);
}
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();
}
}
}
спасибо. Это все решило. Но я все еще придерживаюсь того, что мой запрос регистрируется дважды. Что-то не так с моим классом ServiceGenerator? Я отредактировал свой вопрос –
Сначала попробуйте кэшировать свой служебный объект из 'ServiceGenerator.createService (ApiService.class, token)' или использовать токен в качестве параметра - документы говорят, что есть аннотация @Header, которую вы можете использовать для сопоставьте параметр с заголовком. Наконец, если вы просто хотите сохранить результаты, я добавил редактирование. –
Я прекратил использовать аннотацию @header после ее использования один раз в «Retrofit 1.9», и это не сработало. Однако я использую 'Retrofit 2.1'. Попробуем еще раз –