链条可流动,可完成动作

时间:2017-07-27 08:07:59

标签: android sql rx-android android-room

我有Android Room的SQL查询,返回可流动的:

@Query("SELECT * FROM exercices WHERE lang = 'ru' AND id_exercice = :id")
Flowable<Exercices> getExercicesById(int id);

在我的存储库中,我需要获取发出的元素,而不是更改其布尔值,然后调用new方法,必须返回completable。 这就是我的尝试:

@Override
public Completable setExerciseUsed(int id) {
    return mDatabase.exerciseDao().getExercicesById(id)
            .doOnNext(exercise -> exercise.setIs_used(1))
            .flatMapCompletable(exercise ->
                    Completable.fromAction(() -> mFitnessDatabase.exerciseDao().addExercise(exercise)));
}

我也试过了:

Exercices e = mDatabase.exerciseDao().getExercicesById(id).blockingFirst();
    e.setIs_used(0);
    return Completable.fromAction(() -> mDatabase.exerciseDao().addExercise(e));

但是不能正常工作。看起来像flowable会发出许多元素,并且在订阅之后会停留在循环中。

2 个答案:

答案 0 :(得分:0)

由于DAO返回Flowable,因此每次修改表时,它都会发出新数据。 因此,在致电mFitnessDatabase.exerciseDao().addExercise(exercise)之后, getExercicesById将发出新数据,因此链将永远执行。
如果要让Room不发射数据-只需将Flowable更改为Single。
由于您希望返回一个值e,因此最好将结果限制为一个项目:"SELECT * FROM exercices WHERE lang = 'ru' AND id_exercice = :id LIMIT 1"

但是实际上,如果您要更改项目的参数,则在一个查询中执行此操作会更有效。
可能看起来像:

@Query("UPDATE exercices SET is_used = 1  WHERE lang = 'ru' AND id_exercice = :id")
fun setIsUsed(id: Int)

答案 1 :(得分:-1)

我不太了解flowables或如何取消订阅一个来源,但你有没有想过使用LiveData?您可以简单地将一个源添加到LiveData对象,然后删除与源的连接,更改对象并执行您的方法而不进入循环。

另一个想法是你检索你的对象,保持连接并更新其外的值。因为您要保持与LiveData的数据库连接,观察者将再次执行onChanged(因为source = database已更改)。您只需要确保此方法暂时返回null(通过setValue),直到数据库上传新对象值为止。

如果你想留在flowables,也许你应该考虑添加一个条件,这将阻止应用程序将整数重新应用于对象(并将其发送到数据库)。这对你有意义吗?