当数据库插入失败时将 RetryWhen 添加到 Single

Add RetryWhen to Single When DB Insert Fails

我一直在努力解决这个问题,这对 RXJava 来说仍然是新的,但仍然不喜欢它,而是使用 Livedata 和协程,但无论如何..我有这个:

Single.just(entity)
    .map {
         insertDb(it)
         return@map it
    }
.doOnSubscribe { Timber.d("Updating in database") }
.doOnSuccess { Timber.d("Added row in database") }
.doOnError { Timber.e(it, "Unable to insert object in db") }


fun insertDb(entity: T) {
    try {
       // basic update or insert database.begingTransaction() and endTransaction()
    } catch (e: SQLiteDatabaseLockedException) {}
}

所以当数据库锁定的错误发生时,我想捕获它并使用带有 retryWhen() 的 Single 重试插入。我读到的例子非常复杂,不是我想要的。不要担心锁定的数据库,这只是我如何捕获数据库错误的一个示例。

如果您只想在流中发生特定异常时重试,retry(N) 运算符在这里可能会更好。 (其中 N 是您要重试订阅的最大次数)。

Single.just(entity)
    .map {
         insertDb(it)
         return@map it
    }
    .retry(1) { e -> e is SQLiteDatabaseLockedException }

你也不想在你的 insertDb() 函数中捕获异常,让它落入错误流,这样你就可以在你的 retry 函数中捕获它。

您可能还想考虑从 insertDb() 返回一个 SingleCompletable,然后您可以像 insertDb(entity).retry(1)... 一样调用它,而不使用那个笨拙的 map returns 本身。

你的 insertDb() 函数会变成这样:

fun <T> insertDb(entity: T): Completable {
    return Completable.fromCallable {  
        // Insert operation
    }
}

您可以使用 PublishProcessor:

 val retryProcessor = PublishProcessor.create<Unit>()

 Single.just("Entity")
       .map { insertDB(it) }
       .doOnError { Log.e(TAG, "Error") }
       .retryWhen { retryProcessor }
       .subscribe { entity -> Log.i(TAG, "Success: $entity") }

插入数据库:

fun insertDB(entity: String): String {
    // Insert to DB
    return entity
}

每当您想重试时,请在 PublishProcessor 上调用 onNext:

retryProcessor.onNext(Unit)