Поток RxJava не ожидает результата - PullRequest
0 голосов
/ 04 июля 2018

У меня есть этот метод, который я пытаюсь получить данные из API, а затем обновить текстовое представление. Все работает, за исключением того, что getRecipeName не завершает работу после того, как «метод завершения» log. .getRecipeName() использует RetroFit для извлечения из API.

В настоящее время я изучаю MVP, Dagger, RxJava и Butterknife одновременно, используя Страница Mindork's Github по архитектуре MVP

Я прокомментировал .subscribeOn и .observeOn, чтобы увидеть разницу в результатах, и ничего не изменилось.

@Override
public void onRandomButtonClicked() {

    getMvpView().showLoading();
    Log.e(TAG, "Random Method Open");
    getCompositeDisposable().add(getDataManager()
            .getRecipeName()
            //.subscribeOn(getSchedulerProvider().io())
            //.observeOn(getSchedulerProvider().ui())
            .subscribe(new Consumer<String>() {
                @Override
                public void accept(String s) throws Exception {
                    Log.e(TAG, "accept");
                    getMvpView().updateTextView(title);
                }
            }));

    Log.e(TAG, "end method");

}

Вот мой метод getRecipeName ()

@Override
public Observable<String> getRecipeName() {

    /*Create handle for the RetrofitInstance interface*/
    GetDataService service = RetrofitClientInstance.getRetrofitInstance().create(GetDataService.class);
    Call<RecipeList> call = service.getRecipe();
    call.enqueue(new Callback<RecipeList>() {
        @Override
        public void onResponse(@NonNull Call<RecipeList> call, @NonNull retrofit2.Response<RecipeList> response) {


            Log.e("onResponse","Recipe is Successful = " + response.isSuccessful());
            //if response is false then skip to avoid null object reference
            if (response.isSuccessful()) {

                RecipeList drinkRecipe = response.body();

                List<Recipe> recipes = drinkRecipe.getDrinks();
                jokeText = String.valueOf(recipes.size());
                Recipe myRecipe = recipes.get(0);
                jokeText = myRecipe.getStrDrink();

                Log.e("On Response", "Result2: " + jokeText);
            }
            //jokeText = "null";

        }

        @Override
        public void onFailure(Call<RecipeList> call, Throwable t) {
            Log.e("On Response","Failure");
        }
    });

    //return jokeText;
    return Observable.fromCallable(new Callable<String>() {
        @Override
        public String call() throws Exception {
            return jokeText;
        }
    });
}

Решение

Так что, как отмечалось в комментариях, RxJava Adapter был верным путем. Я просто опубликую свой рабочий код на себе, используя адаптер. Мне было очень трудно найти рабочий пример.

//single api call using retrofit and rxjava
@SuppressLint("CheckResult")
private void getRandomButtonClick(){

    retrofit = RetrofitClientInstance.getRetrofitInstance();

    retrofit.create(GetDataService.class).getRecipe()
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(this::handleResults, this::handleError );
}

private void handleResults(RecipeList recipeList) {
    int i = recipeList.getDrinks().size();
    Log.e(TAG, "size is: "+ i);
    Recipe recipe = recipeList.getDrinks().get(0);
    getMvpView().updateTextView(recipe.getStrDrink());
}

 private void handleError(Throwable t){
    Log.e("Observer", "");

}

Мой модифицированный клиентский экземпляр

 public static Retrofit getRetrofitInstance() {
    if (retrofit == null) {
        retrofit = new retrofit2.Retrofit.Builder()
                .baseUrl(BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();
    }
    return retrofit;
}

Мой интерфейс

public interface GetDataService {

//@Headers({})
@GET("random.php")
Observable<RecipeList> getRecipe();

Я нашел отличный ресурс для справки, чтобы правильно реализовать это. Модернизация Android

1 Ответ

0 голосов
/ 04 июля 2018

Причина в том, что ваша заметка возвращает jokeText каждый раз, когда она подписана. Он возвращается сразу после вызова и не будет ждать вашей сетевой операции.

Одним из возможных решений является использование RxJavaCallAdapter. Ссылка здесь: https://github.com/square/retrofit/tree/master/retrofit-adapters/rxjava2

Он автоматически преобразует возврат API в наблюдаемые. Нет необходимости вручную вызывать запросы на модернизацию. Просто обработайте ответ и оттуда конвертируйте его в нужный объект.

Другой подход - заключить всю последовательность в Observable.create или Observable.fromAsync.

...