Вставка RoomDB застревает при установленной стратегии onConflict - PullRequest
0 голосов
/ 13 июля 2020

Entity:

@Entity(tableName = "users_table")
data class User(
  @PrimaryKey val id: String,
  val name: String = "",
  val surname: String = "",
  val email: String = "",
  val phone: String = "",
  val likes: List<String> = listOf()
)

Dao:

@Dao
abstract class UsersDao {
  @Query("SELECT * FROM users_table WHERE id=:uid")
  abstract fun observeUser(uid: String): Observable<User>

  @Query("SELECT * FROM users_table WHERE id=:uid")
  abstract fun selectUser(uid: String): Single<User>

  @Insert
  abstract fun insertUser(user: User): Completable

  @Update
  abstract fun updateUser(user: User): Completable
}

Когда я звоню insertUser в первый раз, он проходит без проблем. Когда я вызываю его во второй раз, он выдает ошибку из-за конфликта в БД, вызвавшего ошибку @PrimaryKey. Когда я добавляю onConflict=OnCoinflictStrategy.REPLACE к аннотации @Insert, она никогда не завершается. Я поставил точку останова в сгенерированные классы, и оба beginTransaction и endTransaction вызываются внутри. Они вызываются внутри моего источника:

    override fun fetchUser(): Completable =
      authProvider.signedInUserUid
        .flatMap { apiService.getUser(it) }
        .flatMapCompletable { usersDao.insertUser(it) }
        .doOnError { Timber.e(it) }
        .onErrorComplete()
        .observeOn(Schedulers.io())
        .subscribeOn(Schedulers.io())

UPDATE: Когда flatMapCompletable завершается, он не продолжается. Зачем? Когда я моделирую и возвращаю Completable.error() и цепочку onErrorComplete, все продолжается, как и ожидалось. Когда onErrorComplete удаляется, это заканчивается ошибкой, как и ожидалось. Почему он не продолжается, когда завершается? fetchUser вызывается в другом методе rx, который подписан в модели представления:

    override fun isSignedIn(): Completable =
      currentUserExists()
        .andThen(Completable.defer { fetchUser() })
        .onErrorResumeNext {
            Timber.d("Failed initial $it")
            when (it) {
                is SignInException -> signInAnonymously()
                is NoInternetConnection -> Completable.error(it)
                else -> throw NotImplementedError("${it::class.java.name} no implemented")
            }
        }

1 Ответ

0 голосов
/ 14 июля 2020

Причина, по которой он не завершился, состоит в том, что authProvider.signedInUserUid - это BehaviorSubject. flatMapCompletable не завершается, пока не завершится начальный поток, в данном случае signedInUserUid. Заменен BehaviorSubject методом, возвращающим Observable.just(), исправлена ​​проблема, когда он завершается после выдачи значения.

...