Anshul Tyagi
Anshul Tyagi

Reputation: 2196

RxJava How to return more than 2 ArrayLists within Observable in a function

I'm able to pass two lists via observable as it is mentioned below

fun loadAll(contact: String?): Single<Pair<ArrayList<Contact>, ArrayList<Contact>>> {
    return packageDB.loadAll()
        .map { table ->
            val one = ArrayList< Contact >()
            val two = ArrayList< Contact >()
            val three = ArrayList< Contact >()
            
            one to two
        }
} 

And in Fragment, I'm trying to return as:

  disposables.add(
        viewModel.loadAll(contact)
            .subscribe({
                val firstList = it.first
                val secondList = it.second
                val third = ArrayList<Contact>()
 }))
              

I'm new to reactive programming so I'm unable to understand how I can pass or return more than two lists as Pair object can have two child objects only. I would be thankful if you can let me know the solution.

Upvotes: 0

Views: 332

Answers (1)

Fred
Fred

Reputation: 17085

There is more than one way of doing this, I can list some. You simply have to think of the return object. If you want to return 3 things only, I wouldn't even bother with creating a specific class if it's clear what you're doing. Kotlin has already a class for this - Triple. It's like a pair, but holds 3 values:

fun loadAll(contact: String?): Single<Triple<ArrayList<Contact>, ArrayList<Contact>, ArrayList<Contact>>> {
    return packageDB.loadAll()
        .map { table ->
            val one = ArrayList< Contact >()
            val two = ArrayList< Contact >()
            val three = ArrayList< Contact >()
            
            Triple(one, two, three)
        }
} 

And then access them as:

disposables.add(
        viewModel.loadAll(contact)
            .subscribe({
                val firstList = it.first
                val secondList = it.second
                val third = it.third
 }))

If you have more than 3 values, I'm not sure if there's already a class for this, but there's always the option of using arrays of arrays:

fun loadAll(contact: String?): Single<Array<ArrayList<Contact>> {
    return packageDB.loadAll()
        .map { table ->
            val one = ArrayList< Contact >()
            val two = ArrayList< Contact >()
            val three = ArrayList< Contact >()
            
            arrayListOf(one, two, three)
        }
} 


disposables.add(
        viewModel.loadAll(contact)
            .subscribe({ (firList, secondList, thirdList) ->
                  // the above destructures the list into 3 variables
                  // if the list has less than 3 elements you'll get an index out of bounds exception
                  // otherwise you can just use the variables
 }))

As pointed out in the comments, this might create some problems understanding what each value is, so sometimes it's better to create your own class:

data class Values(
   val primaryContacts: ArrayList< Contact >(),
   val secondaryContacts: ArrayList< Contact >(),
   val emergencyContacts: ArrayList< Contact >(),
)

fun loadAll(contact: String?): Single<Values> {
    return packageDB.loadAll()
        .map { table ->
            val one = ArrayList< Contact >()
            val two = ArrayList< Contact >()
            val three = ArrayList< Contact >()
            
            Values(one, two, three)
        }
} 

disposables.add(
        viewModel.loadAll(contact)
            .subscribe({
                val firstList = it.primaryContacts
                val secondList = it.secondaryContacts
                val third = it.emergencyContacts
 }))

please excuse the naming. It's just an example.

Upvotes: 1

Related Questions