SQLite事务和RxJava

时间:2016-08-21 11:13:49

标签: android-sqlite rx-java rx-android

我可以使用RxJava保存数据:

override fun put(note: Note): Observable<Note> {
    validateNote(note)
    return Observable.just(note)
            .doOnNext { dbKeeper.startTransaction() }
            .doOnNext { storeHashtags(note) }
            .doOnNext { storeImages(note) }
            .flatMap { notesDataStore.put(notesMapper.transform(note)) }
            .map { notesMapper.transform(it) }
            .doOnNext { dbKeeper.setTransactionSuccessful() }
            .doOnUnsubscribe { dbKeeper.endTransaction() }
}

然后我像这样使用这个方法:

      notesManager.put(note)
            .switchMap { notesManager.getHashtags() }
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe {view.setHashtags(it) }

doOnUnsubscribe从未调用getHashtags()尝试从startTransaction()锁定的数据库中进行SELECT。死锁,嘿。 好的。我们将doOnUnsubscribe(...)替换为doOnTerminate(...)

override fun put(note: Note): Observable<Note> {
    validateNote(note)
    return Observable.just(note)
            .doOnNext { dbKeeper.startTransaction() }
            .doOnNext { storeHashtags(note) }
            .doOnNext { storeImages(note) }
            .map { notesMapper.transform(note) }
            .flatMap { notesDataStore.put(it) }
            .map { notesMapper.transform(it) }
            .doOnNext { dbKeeper.setTransactionSuccessful() }
            .doOnTerminate { dbKeeper.endTransaction() }
}

但是,如果Observable subscriber.unsubscribe()被{{1}}中断,现在交易将不会关闭。

你可以推荐什么来解决我的情况?

其他信息: 我使用一个writableDb实例来写/读数据。

1 个答案:

答案 0 :(得分:1)

我认为这不适合Rx;我的建议是使用通常的try-finally进行事务处理(原谅Java):

Observable<Note> put(Note note) {
   return just(note)
        .doOnNext(n -> {
            validateNote(n);
            dbKeeper.startTransaction();
            try {
              storeHashtags(n);
              storeImages(n);
              notesDataStore.put(notesMapper.transform(n));
              dbKeeper.setTransactionSuccessful();
            } finally {
              dbKeeper.endTransaction();
            }
         });
}

编辑:也许这更有用:

fun <T> withTransaction(sourceObservable: Observable<T>): Observable<T> {
    val latch = AtomicInteger(1)
    val maybeEndTransaction = Action0 {
        if (latch.decrementAndGet() == 0) {
            endTransaction()
        }
    }
    return Observable.empty<T>()
            .doOnCompleted { startTransaction() }
            .mergeWith(sourceObservable)
            .doOnNext { setTransactionSuccessful() }
            .doOnTerminate(maybeEndTransaction)
            .doOnUnsubscribe(maybeEndTransaction)
}

像这样使用:

override fun put(note: Note): Observable<Note> {
  return Observable.just(note)
        .doOnNext { validateNote(note) }
        .doOnNext { storeHashtags(note) }
        .doOnNext { storeImages(note) }
        .flatMap { notesDataStore.put(notesMapper.transform(note)) }
        .map { notesMapper.transform(it) }
        .compose { withTransaction }
}

它将确保交易完成一次;请注意不要在原始可观察链中切换线程(除非您的事务管理器可以处理它,或者您修改了调度程序以将新线程与现有事务相关联)。