Working with RxJava Disposables in Kotlin
In this tutorial, you’ll learn the basics of RxJava Disposables. You will be building an app from scratch that retrieves real-time cryptocurrency data. By Lawrence Tan 🇸🇬.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Working with RxJava Disposables in Kotlin
20 mins
In this tutorial, you’ll learn the basics of RxJava Disposables. You’ll build an app from scratch that retrieves real-time cryptocurrency data.
Note: This tutorial assumes you have some experience using RxJava. If you don’t, make a pit stop at this tutorial first before proceeding.
Note: This tutorial assumes you have some experience using RxJava. If you don’t, make a pit stop at this tutorial first before proceeding.
Reactive Android Programming consists of RxJava, RxAndroid and RxKotlin.
RxJava is the most touted Reactive Programming library in the Android Development world. It reduces many threading headaches and makes codes more intuitive.
RxAndroid is a lightweight module which binds Android specific components with RxJava classes.RxKotlin makes writing RxJava methods easier by providing convenient extension functions.
RxAssemble! You’ll use the basic functions of these three libraries to build the CryptoMe app in this tutorial.
Disposables
What are Disposables? Disposable in plain English implies short-term convenience. This also means they are short lived or meant to be discarded after use. The same idea is conveyed in RxJava’s Disposables.
When an Observer subscribes to an Emitter, or Observables, you create a stream. This stream takes up resources which later become disposable “solid waste”. You need to handle this waste if the stream is going to run for a long time.
Observable
has a method called onComplete()
that will do the disposing for you when called. Many at times though, you will find it more beneficial and convenient to have the ability to cancel your subscriptions easily and at any time.
Today, you’ll tackle a more complex case. The stream will run endlessly and you’ll use Disposable
s to handle them to prevent memory leaks.
A Disposable
is a stream or a link between an Observable
and an Observer
. A quick check of the documentation shows that it has two main methods, dispose()
and isDisposed()
. The former disposes of the link, while the latter checks if the link has been disposed.
Testing Disposables
When you establish a subscription between Observable
and Observer
, it returns a Disposable
. For example, take a look at this code:
import android.util.Log
import io.reactivex.Observable
import java.util.concurrent.TimeUnit
object DisposableTester {
@JvmStatic fun main() {
val seconds = Observable.interval(1, TimeUnit.SECONDS)
val disposable = seconds.subscribe({ l -> logData(l) })
//sleep 10 seconds
sleep(10000)
//Dispose and stop emissions
disposable.dispose()
Log.d("Test","Disposed!")
//Sleep 10 seconds to prove
//There are no more emissions
sleep(10000)
}
private fun logData(l: Long) {
Log.d("Test","Received: " + l)
}
private fun sleep(millis:Int) {
try {
Thread.sleep(millis.toLong())
}
catch (e:InterruptedException) {
e.printStackTrace()
}
}
}
An Observable
runs and emits every second. After ten seconds of emissions, the Disposable
resource returned from subscribe()
is disposed of by explicitly calling dispose()
. Then another ten seconds timer emits to verify that the resource is already disposed of.
Handling Disposable
s outside is one way to dispose of resources that are no longer needed. Since RxJava 2.0, the Observer has the ability to dispose of the subscription at any time. For an example:
import io.reactivex.Observer
import io.reactivex.disposables.Disposable
object DisposableTester {
var myObserver: Observer<Int> = object: Observer<Int> {
private var disposable: Disposable? = null
override fun onSubscribe(disposable: Disposable) {
this.disposable = disposable
}
override fun onNext(value:Int) {
//Has access to Disposable
}
override fun onError(e:Throwable) {
//Has access to Disposable
}
override fun onComplete() {
//Has access to Disposable
}
}
}
If at any time the emissions are no longer required in onNext()
, onError()
or onComplete()
, you can stop them.
CompositeDisposables
As the app evolves, there are scenarios where you need more than one subscription. Retrieving live data from multiple sources in a travel app for hotel, tours and air tickets is one great example.
You need to use CompositeDisposables to manage the resources. It implements Disposable
and then holds a collection of disposables. Here’s a quick example:
import android.util.Log
import io.reactivex.Observable
import io.reactivex.disposables.CompositeDisposable
import java.util.concurrent.TimeUnit
object DisposableTester {
private val disposables = CompositeDisposable()
@JvmStatic fun main() {
val seconds = Observable.interval(1, TimeUnit.SECONDS)
//Subscribe and capture disposables
val disposable1 = seconds.subscribe({ l -> logData(l, 1) })
val disposable2 = seconds.subscribe({ l -> logData(l, 2) })
//Put both disposables into CompositeDisposable
disposables.addAll(disposable1, disposable2)
//Sleep 10 seconds
sleep(10000)
//Dispose all disposables
disposables.dispose()
Log.d("Test", ("All Disposed!"))
//Sleep 10 seconds to prove
//there are no more emissions
sleep(10000)
}
private fun logData(l: Long, observerNumber: Int) {
Log.d("Test", ("Observer " + observerNumber + ": " + l))
}
private fun sleep(millis:Int) {
try {
Thread.sleep(millis.toLong())
} catch (e:InterruptedException) {
e.printStackTrace()
}
}
}
In this implementation, the code leveraged on this simple utility which helps you manage a collection of Disposable
s. By calling add()
or addAll()
, you can dispose of them all at once when they’re no longer needed.
Congratulations! You’ve refreshed your knowledge on the basics of Reactive Programming and learned about Disposable
s. Now, you’re ready to embark on a journey in building the CryptoMe App!
CryptoMe App
Before you get started, take a look at what the app will look like once you’ve completed this tutorial.
The main page has two tabs. The Western Tab loads Crypto data from Western countries while the Eastern Tab loads Crypto data from Eastern countries.
The data comes from CryptoCompare API. You can sign up here for a free key with limited calls. The app polls for updated data every ten seconds.
By tapping on any Cryptocurrency, the app brings you to its web contents. You’ll learn to use Disposable
s to manage resources in this app.
Are you ready? Time to get started!
Getting Started
To get started, click on the Download Materials button at the top or bottom of this tutorial. First, explore the starter project in Android Studio 3.4.1 and above.
You’ll work on BaseFragment.kt where most of the network handling logic is. You’ll also implement some configurations in CryptoDataRepository.kt and CryptoDataViewModel.kt.
Take a look at some of the files. In App.kt, you’ll find Retrofit is the main network utility the app uses. In this file, you initialize Retrofit
and use CryptoDataAPI
to manage API calls.
CryptoDataRepository
is a class which accepts an object and implements CryptoDataAPI
. This class helps handle specific server data logic.
When the Observable
receives data, it’ll process and integrate into CryptoDataViewModel
. The ViewModel updates the RecyclerView which displays to users the latest crypto data.
The MainActivity
contains a TabLayout, with each tab holding a single Fragment. HomeFragment
and SecondFragment
both inherit from BaseFragment
, where most of the data processing work is.
FragmentAdapter
helps populate the appropriate Fragment in each Tab. CryptoDataAdapter
helps translate Data into RecyclerViews.
DetailActivity
shows the web contents of a selected cryptocurrency.
Wow, that’s a lot to process!
Fear not! Having an organized project structure does reap benefits. You’ll see at the end how everything pieces together to build your very own CryptoMe app!
Now, build and run the project on your Android device or emulator. You should see a gorgeous empty search screen: