将RxJava2 Db查询到另一个主题

时间:2017-02-16 10:11:13

标签: android rx-java reactive-programming rx-java2

在我的Android项目中,我非常依赖RxJava2SqlBrite(使用RxJavaInterop)和SqlDelight

我有一个rx流应该是无限期(直到我的服务停止)并且在其上我有一个.flatMap Function<String, ObservableSource<Action>>

意思是,这个flatMap包含Subject<Action>,会收到String actionId,对这些actionId执行一些(与问题无关)处理,并且根据条件应查询数据库中的Action对象并将其发送到subject

我的第一个方法是直接进行查询:

Cursor c = db.query(...);
if(c.moveFirst()) {
    Action a = Action.SELECT_ALL_MAPPER.map(c);
    subject.onNext(selectAll);
}

但这阻止了正在运行的线程,我宁愿在自己的流上触发它,应该执行以下操作:

  • 查询(应返回0或1项)
  • 如果有值:映射到Action对象并将值推送到subject
  • 如果没有价值:终止/处置。
  • subject无法收到终止或错误。它必须为未来的活动保持活力。

我目前的方法是以下代码:

RxJavaInterop.toV2Observable(db.createQuery(
    Action.TABLE_NAME,
    Action.FACTORY.Select_by_id(actionId).statement)
    .mapToOne(new Func1<Cursor, Action>() {
        @Override public Action call(Cursor cursor) {
            return Action.SELECT_ALL_MAPPER.map(cursor);
        }
    }))
    .take(1)
    .subscribe(new Consumer<Action>() {
        @Override public void accept(Action action) throws Exception {
            subject.onNext(action);
        }
    });

虽然这似乎是第一印象的诀窍,但我看到它上面有一些错误:

  • 我无法处理它。即使我得到了对Disposable对象的引用,我也无法从Consumer<Action>内部调用它,因为它“可能尚未初始化”(我明白原因,没关系)。
  • 如果没有给定ID的动作,observable将永远挂在那里,直到VM被杀死。

所以问题:

我该怎么做?

1 个答案:

答案 0 :(得分:1)

  

我宁愿在自己的流上触发

看看RxAndroid。这看起来像是:

yourRxStream
    .flatMap(*db request here*)
    .subscribeOn(Schedulers.io())
    .subcribe(subject);
  

subject无法收到终止或错误。它必须活着   未来的事件。

使用Relay

切换主题
  

主题对于弥合非Rx API之间的差距很有用。然而,   他们以有害的方式有条不紊:当他们收到onComplete时   或onError它们不再可用于移动数据。这是   可观察的合同,有时它是理想的行为。最   时间不是。

     

继电器只是没有上述属性的主题。他们   允许您轻松地将非Rx API桥接到Rx,而无需担心   意外触发终端状态。

最后,对于请求而不是输出0或1项,请使用Maybe