Created
August 6, 2020 13:03
-
-
Save Evin1-/847299ff79f9f5268cbfe57668c854bb to your computer and use it in GitHub Desktop.
Loop Cupcakes. Doing 2 network calls using RxJava Zip operator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<uses-permission android:name="android.permission.INTERNET" /> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
android { | |
//.. | |
compileOptions { | |
sourceCompatibility JavaVersion.VERSION_1_8 | |
targetCompatibility JavaVersion.VERSION_1_8 | |
} | |
} | |
dependencies { | |
//.. https://square.github.io/retrofit/ | |
//.. https://github.com/ReactiveX/RxAndroid | |
//.. https://github.com/akarnokd/RxJavaRetrofitAdapter | |
implementation 'com.squareup.retrofit2:retrofit:2.9.0' | |
implementation 'com.squareup.retrofit2:converter-moshi:2.9.0' | |
implementation 'io.reactivex.rxjava3:rxandroid:3.0.0' | |
implementation 'io.reactivex.rxjava3:rxjava:3.0.5' | |
implementation "com.github.akarnokd:rxjava3-retrofit-adapter:3.0.0" | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class MainActivity : AppCompatActivity() { | |
override fun onCreate(savedInstanceState: Bundle?) { | |
super.onCreate(savedInstanceState) | |
setContentView(R.layout.activity_main) | |
/* Creates an instance of the UserService using a simple Retrofit builder using Moshi | |
* as a JSON converter and an RxJava adapter, this will append the endpoints set on | |
* the UserService interface (for example '/api', '/api?results=2') with the base URL | |
* set here, resulting on the full URL that will be called: 'https://randomuser.me/api' */ | |
val service = Retrofit.Builder() | |
.baseUrl("https://randomuser.me/") | |
.addCallAdapterFactory(RxJava3CallAdapterFactory.create()) | |
.addConverterFactory(MoshiConverterFactory.create()) | |
.build() | |
.create(UserService::class.java) | |
/* The RxJava Single that will call the user info endpoint */ | |
val userInfoSingle = service.getUserInfo().map { it.results.first() } | |
/* The RxJava Single that will call the followers endpoint endpoint */ | |
val followersSingle = service.getFollowers(10).map { it.results } | |
/* RxJava chain that calls the 2 endpoints in parallel, their results are going to be | |
* merged after they are both done using the UserZipper object, both calls will be made | |
* on a worker thread and then come back to the main thread using the subscribeOn and | |
* observeOn combination in the chain. If any of the calls fail, the whole RxJava chain | |
* will fail using the onError callback. The logging of either the error or completion | |
* of the operation is run on the main thread. */ | |
Single.zip(userInfoSingle, followersSingle, UserZipper) | |
.subscribeOn(Schedulers.io()) | |
.observeOn(AndroidSchedulers.mainThread()) | |
.subscribe({ Log.d("TAG_ ", it) }) { Log.e("TAG_ ", "Error happened! $it") } | |
} | |
} | |
/* A simple zipper that will map the result of both network calls using a String | |
* concatenation. This is run on a worker thread. */ | |
object UserZipper : BiFunction<User, List<User>, String> { | |
override fun apply(user: User, followers: List<User>): String { | |
val followersEmails = followers.map { it.email } | |
return "$user has followers: $followersEmails" | |
} | |
} | |
/* Kotlin data/model classes that map the JSON response, we could also add Moshi | |
* annotations to help the compiler with the mappings on a production app */ | |
data class UserResponse(val results: List<User>) | |
data class User(val email: String, val phone: String) | |
/* Retrofit service that maps the different endpoints on the API, you'd create one | |
* method per endpoint, and use the @Path, @Query and other annotations to customize | |
* these at runtime. These are just simulations to get a single and a list of users. */ | |
interface UserService { | |
@GET("/api") | |
fun getUserInfo(): Single<UserResponse> | |
@GET("/api") | |
fun getFollowers(@Query("results") results: Int): Single<UserResponse> | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment