可流动的房间:初始化数据库,如果它是空的

azi*_*ian 1 android kotlin rx-java rx-java2 android-room

我有以下@Dao,提供Flowable<User>流:

@Dao
interface UsersDao {
  @Query("SELECT * FROM users")
  fun loadUsers(): Flowable<List<User>>
}
Run Code Online (Sandbox Code Playgroud)

我希望流的订户在那里发生一些变化时立即接收数据库的更新.订阅Room Flowable我将获得开箱即用的功能.

我想要的是:如果数据库为空我想执行Web请求并将用户保存到数据库中.订阅者将自动接收刚刚发生的新更新.

现在我希望存储库的客户端不要知道所有的初始化逻辑:他所做的一切 - 他执行usersRepository.loadUsers().所有这些魔法应该发生在存储库类中:

class UsersRepository @Inject constructor(
    private val api: Api,
    private val db: UsersDao
) {

  fun loadUsers(): Flowable<List<User>> {
    ...
  }
}
Run Code Online (Sandbox Code Playgroud)

当然我可以使用以下方法:

fun loadUsers(): Flowable<List<User>> {
  return db.loadTables()
      .doOnSubscribe {
        if (db.getCount() == 0) {
          val list = api.getTables().blockingGet()
          db.insert(list)
        }
      }
}
Run Code Online (Sandbox Code Playgroud)

但我想在不使用副作用(doOn...运算符)的情况下构造流.我尝试过,composing()但没有多大帮助.被困在这一段时间了.

aka*_*okd 7

您可以应用一些条件flatMaps:

@Dao
interface UsersDao {
    @Query("SELECT * FROM users")
    fun loadUsers(): Flowable<List<User>>

    @Query("SELECT COUNT(1) FROM users")
    fun userCount() : Flowable<List<Integer>>

    @Insert // I don't know Room btw.
    fun insertUsers(List<User> users) : Flowable<Object>
}

interface RemoteUsers {
     fun getUsers() : Flowable<List<User>>
}

fun getUsers() : Flowable<List<User>> {
     return
         db.userCount()
         .take(1)
         .flatMap({ counts ->
             if (counts.isEmpty() || counts.get(0) == 0) {
                 return remote.getUsers()
                        .flatMap({ users -> db.insertUsers(users) })
                        .ignoreElements()
                        .andThen(db.loadUsers())
             }
             return db.loadUsers()
         })
}
Run Code Online (Sandbox Code Playgroud)

免责声明:我不知道房间,所以请调整上面的例子,因为它的功能允许.