将RxJava主题转换为可观察对象

时间:2019-04-26 23:29:59

标签: android rx-java rx-java2 android-viewmodel

我最近遇到了关于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()时发出刷新事件,然后将其传播到BehaviorSubjectgetWeatherDataToDisplay()成功后,将通知所有观察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一样无缝地分离和重新附加。

如果您看到可以改进的地方,或者对问题有不同的解决方法,请分享您的想法。

0 个答案:

没有答案