How to get two different types onto the same stream?


Let’s say that you have two rest calls. One call that takes a user id and returns a profile. And another that again takes a user id but this time returns a list of favorites.  Essentially you have two types you want on the same stream.

The function calls might respectively look like the following:

fun getProfile(id: UUID): Single

fun getFavorites(id: UUID): Single

Let’s say that Profile looks like the following:

data class Profile(val id: UUID, val email: String, val firstName: String, val lastName: String)

And that Favorites looks like the following:

data class Favorites(val id: UUID, val favorites: List)

The issue is that the types the return aren’t the same. So how would we merge these two items into one?

One way is with zip.

Using the Zip Operator

The zip operator marble diagram looks like the following:

Zip Marble Diagram for Merging Different Types

There are two different streams of different types that become one type at the end. Here is what zip looks like:

public static <T1, T2, R> Single zip(
       SingleSource<? extends T1> source1, SingleSource<? extends T2> source2,
       BiFunction<? super T1, ? super T2, ? extends R> zipper
)

If you are enjoying this you may want to check out my Essential RxJava Guide for Android Developers

This might look intimidating at first glance. But breaking it down it only has three different parts. It takes two different single sources. These will be our observables for profile and favorites. And a third parameter which is a Bifunction. This will be our combining function, given two items in one item will go out.

Since we need a container object to hold both values we can define an extended profile class that takes profile and favorites:

data class ExtendedProfile(val profile: Profile, val favorites: Favorites)

Using Zip we end up with something like this:

Single.zip<Profile, Favorites, ExtendedProfile>(getProfile(uuid), getFavorites(uuid), BiFunction { profile, favorites ->
   ExtendedProfile(profile, favorites)
})

And of course if we print it out we can see both profile and favorites are there.

ExtendedProfile(profile=Profile(id=9e79541d-7b1c-48d5-b8a1-667177f4c63b, email=john@random.com, firstName=John, lastName=Doe), favorites=Favorites(id=9826ed13-ad5a-4e1c-9dfb-61c22ecfe47c, favorites=[Song(id=6e7ab44f-7dbf-4a28-8b8c-046a931dd3a1, title=Werld is mine, album=You're a man now, boy, author=Raleigh Ritchie)]))

Awesome! We used the zip operator to combine two different object types into one.

BEFORE YOU GO
Get this FREE guide to RxJava with a bonus chapter that will help you avoid RxJava beginner mistakes.

I'll show you the exact mistakes and solutions so that you can jumpstart your Rx Development such as:

  • Avoiding bugs due to concurrency configuration
  • Avoiding bugs with multiple subscriptions
  • Avoiding bugs due to error handling mistakes


I'll even throw in the full guide as a PDF

Comments 1

  1. Nice. Definitely could have used that in an Android app I made last year. I was using a few AWS services with AsyncTask. I had multiple requests going on at the same time: one to see if the session had expired, one to get the content for the main RecyclerView, and another to fetch profile/other data. I learned a lot from the experience. Thanks for the RxJava course!

Leave a Reply

Your email address will not be published. Required fields are marked *