Alex Busuioc
Alex Busuioc

Reputation: 1182

RxJava2 - Combine multiple Singles emitted results into a Map

I fetch a List<User> from the server.

class User {
  Long localId;
  String remoteId;
  ..
}

I need to insert each user from the list into the local db, and in the end get a HashMap<String,Long> (an object that maps remoteId to localId)

Each insertToLocalDb returns a Single<Long>. Thus, the Observable emits the inserted User's localId

How can I achieve this in a reactive way?

Upvotes: 1

Views: 3267

Answers (1)

Ahmed Ashraf
Ahmed Ashraf

Reputation: 2835

First of all I have to suggest using a transaction for multiple db operations, which is your case.

A trivial non-performant solution might look like this:

fetchUsers()
  .flatMap { users ->
        Observable.fromIterable(users)
            .flatMapSingle { user -> dao.save(user) }
            .toList()
            .map { databaseIds ->
                val remoteIds = users.map { it.remoteId }
                databaseIds.zip(remoteIds).toMap()
            }

But taking transaction in mind, Room supports this for example, it can go like this:

fetchUsers().flatMap { users ->
        dao.saveAll(users) // typically returns Single<List<Long>>
            .map { databaseIds ->
                val remoteIds = users.map { it.remoteId }
                databaseIds.zip(remoteIds).toMap()
            }
    }

Both will result to Single<Map<String, Long>>, but the second approach is far more performant if you're using a transaction.

Upvotes: 3

Related Questions