0

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.

2
  • 1
    Can you not just create a class to hold whatever you want and return that instead? Commented Sep 29, 2021 at 10:29
  • Agree with @IvanWooll. Create a class that holds whichever data you want and use it in Single<YourClass>. Commented Sep 29, 2021 at 11:12

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks man. I also solved it like this yesterday. Sorry I'm new in Rx so taking time to understand.
No need for apologies. We've all been there and some of us before StackOverflow :D

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.