Преобразование объектов RxJava в наблюдаемые - PullRequest
1 голос
/ 27 апреля 2019

Я недавно столкнулся с вопросом об использовании Subject, как здесь: https://github.com/JakeWharton/RxRelay/issues/7

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


Представьте себе простое теоретическое погодное приложение , которое имеет всего две вещи:

  1. представление, отображающее текущую информацию о погоде

  2. кнопка обновления, которая повторно получает информацию о погоде с сервера.

(Предположим для простоты, что приложение не показывает данные при первом запуске, но ждет, пока пользователи нажмут кнопку обновления хотя бы один раз.)

Тогда вы можете подумать о дизайне модели вида следующим образом:

ViewModel

interface IWeatherViewModel {

    // Provides weather data
    Flowable<WeatherData> getWeatherDataToDisplay();

    // Lets view to refresh
    void refresh();
}

Если я использую Subject, тогда IWeatherViewModel может быть реализовано так:

class WeatherViewModel implements IWeatherViewModel {

    private final BehaviorProcessor<WeatherData> weatherData = BehaviorProcessor.create();
    private final PublishProcessor<Boolean> eventRefresh = PublishProcessor.create();


    WeatherViewModel() {
        eventRefresh
            .flatMapSingle(x -> getWeatherData())
            .subscribe(weatherData);
    }


    // Provides weather data
    public Flowable<WeatherData> getWeatherDataToDisplay() {
        weatherData.hide();
    }

    // Lets view to refresh
    public void refresh() {
        eventRefresh.onNext(true);
    }



    private Single<WeatherData> getWeatherData() {
        ... // omitted for simplicity            
    }
}

Идея состоит в том, чтобы PublishProcessor генерировал событие обновления каждый раз, когда вызывается refresh(), который затем распространяется на BehaviorSubject. Все подписчики, которые наблюдают за getWeatherDataToDisplay(), будут уведомлены, как только getWeatherData() будет успешным.


Однако мне трудно реализовать то же самое без Subject.

  1. Приложение должно распространять refresh() вызов в поток. Я мог бы заменить PublishProcessor, используя Flowable.create(), но он совсем не выглядит чистым, лучшее, что я мог сделать, это:


private FlowableEmitter emitter;
private final Flowable<Boolean> eventRefresh = Flowable.create(emitter -> {
    this.emitter = emitter;
}, BackpressureStrategy.BUFFER);


public void refresh() {
    emitter.onNext(true);
}

Теперь внезапно у меня появилась новая переменная экземпляра, которую я не могу сделать окончательной ..

  1. Также я не могу найти ни одного оператора, который мог бы эффективно заменить BehaviorProcessor, ни какого-либо горячего наблюдаемого, которое испускает последний элемент сразу после подписки. Такое поведение необходимо, потому что представление должно иметь возможность безболезненно отсоединяться и повторно присоединяться, как LiveData.

Если вы видите какие-либо улучшения, которые могут быть сделаны, или у вас другой подход к проблеме, поделитесь своими мыслями.

...