我在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的更好方法吗?为什么?这两种方法实际上有什么区别?
而且,由于数据库加载了一个元素列表,有意义一次发出整个列表?或者我应该一次发出一个项目?
答案 0 :(得分:34)
这两种方法可能看起来相似且行为相似,但fromCallable
处理背压的困难,而create
版本却没有。处理OnSubscribe
实施中的背压范围从简单到完全的心灵融化;但是,如果省略,您可能会沿异步边界(例如MissingBackpressureException
)或甚至连续边界(例如observeOn
)获得concat
。
RxJava试图为尽可能多的工厂和运营商提供适当的背压支持,但是,有不少工厂和运营商无法支持它。
手动OnSubscribe
实施的第二个问题是缺少取消支持,特别是如果您生成了大量onNext
次呼叫。其中许多方法可以替换为标准工厂方法(例如from
)或帮助程序类(例如SyncOnSubscribe
)来处理所有复杂性。
您可能会发现很多介绍和示例(仍然)使用create
有两个原因。
create
按比例而不是谈论标准工厂方法,并展示如何安全地实现某些常见任务(如你的)。对于第二个问题,即如果要创建List或值序列,则取决于您的来源。如果您的源支持某种迭代或单个数据元素的流式传输(例如JDBC),您可以只挂钩并逐个发出(请参阅SyncOnSubscribe
)。如果它不支持它或者你需要它以列表形式,那么保持原样。如有必要,您始终可以通过toList
和flatMapIterable
在两种表单之间进行转换。
答案 1 :(得分:2)
正如您在the response中所解释的那样,与Observable.create
相关联,您可能需要违反RxJava的高级要求。
例如,您需要实施backpressure或如何取消订阅。
在您的情况下,您想要发出一个项目,而不必处理背压或订阅。所以Observable.fromCallable
是一个很好的电话。 RxJava将处理剩下的事情。