不使用Observable.create创建Observable

时间:2015-12-10 14:45:02

标签: android reactive-programming rx-java

我在Android应用中使用RxJava,我想从数据库加载数据。

通过这种方式,我使用Observable.create()创建一个新的Observable,它返回EventLog的列表

public Observable<List<EventLog>> loadEventLogs() {
    return Observable.create(new Observable.OnSubscribe<List<EventLog>>() {
        @Override
        public void call(Subscriber<? super List<EventLog>> subscriber) {
            List<DBEventLog> logs = new Select().from(DBEventLog.class).execute();
            List<EventLog> eventLogs = new ArrayList<>(logs.size());
            for (int i = 0; i < logs.size(); i++) {
                eventLogs.add(new EventLog(logs.get(i)));
            }
            subscriber.onNext(eventLogs);
        }
    });
}

虽然它可以正常工作,但我读到使用Observable.create()实际上并不是Rx Java的最佳实践(参见here)。

所以我用这种方式改变了这个方法。

public Observable<List<EventLog>> loadEventLogs() {
    return Observable.fromCallable(new Func0<List<EventLog>>() {
        @Override
        public List<EventLog> call() {
            List<DBEventLog> logs = new Select().from(DBEventLog.class).execute();
            List<EventLog> eventLogs = new ArrayList<>(logs.size());
            for (int i = 0; i < logs.size(); i++) {
                eventLogs.add(new EventLog(logs.get(i)));
            }
            return eventLogs;
        }
    });
}

这是使用Rx Java的更好方法吗?为什么?这两种方法实际上有什么区别?

而且,由于数据库加载了一个元素列表,有意义一次发出整个列表?或者我应该一次发出一个项目?

2 个答案:

答案 0 :(得分:34)

这两种方法可能看起来相似且行为相似,但fromCallable处理背压的困难,而create版本却没有。处理OnSubscribe实施中的背压范围从简单到完全的心灵融化;但是,如果省略,您可能会沿异步边界(例如MissingBackpressureException)或甚至连续边界(例如observeOn)获得concat

RxJava试图为尽可能多的工厂和运营商提供适当的背压支持,但是,有不少工厂和运营商无法支持它。

手动OnSubscribe实施的第二个问题是缺少取消支持,特别是如果您生成了大量onNext次呼叫。其中许多方法可以替换为标准工厂方法(例如from)或帮助程序类(例如SyncOnSubscribe)来处理所有复杂性。

您可能会发现很多介绍和示例(仍然)使用create有两个原因。

  1. 通过展示事件推送如何以强制方式工作,更容易引入基于推送的数据流。在我看来,这些来源花费了太多时间create按比例而不是谈论标准工厂方法,并展示如何安全地实现某些常见任务(如你的)。
  2. 这些示例中的许多都是在RxJava不需要背压支持或甚至正确的同步取消支持的时候创建的,或者只是从Rx.NET示例移植(迄今为止它不支持背压和同步取消)以某种方式工作,我猜C#的礼貌。)通过调用onNext来生成值当时是无忧无虑的。但是,这样的使用会导致缓冲区膨胀和内存使用过多,因此,Netflix团队提出了一种限制内存使用的方法,要求观察者说明他们愿意继续进行多少项目。这被称为背压。
  3. 对于第二个问题,即如果要创建List或值序列,则取决于您的来源。如果您的源支持某种迭代或单个数据元素的流式传输(例如JDBC),您可以只挂钩并逐个发出(请参阅SyncOnSubscribe)。如果它不支持它或者你需要它以列表形式,那么保持原样。如有必要,您始终可以通过toListflatMapIterable在两种表单之间进行转换。

答案 1 :(得分:2)

正如您在the response中所解释的那样,与Observable.create相关联,您可能需要违反RxJava的高级要求。

例如,您需要实施backpressure或如何取消订阅。

在您的情况下,您想要发出一个项目,而不必处理背压或订阅。所以Observable.fromCallable是一个很好的电话。 RxJava将处理剩下的事情。