MARTIN GORNER: Hello and welcome back
to root access Berlin.
We are recording again from the new studio at the factory,
and today I have with me Mustafa Sezgin from
SoundCloud.
Hello Mustafa.
MUSTAFA SEZGIN: Hi.
MARTIN GORNER: Can you introduce yourself?
MUSTAFA SEZGIN: Sure.
So I'm the director of mobile engineering at SoundCloud, and
I lead up basically the native mobile applications and the
development of those at SoundCloud at the moment.
MARTIN GORNER: And so you wanted to tell us about a
design pattern that you have recently started using at
SoundCloud.
MUSTAFA SEZGIN: Yeah.
So one of the common problems that we have on native mobile
applications is having to obviously have a responsive
user interface, and to do that, you generally need to
jump off the main UI thread to retrieve some work where the
information comes from some IO source, whether that's from
the network or from the data.
There are a lot of components build in to some of these SDKs
that help with that, but one of the recent frameworks that
we've started to use is RxJava, which was developed by
the Netflix guys who have come together and put together
really good library.
And we've started to use that to kind of replace a lot of
the work that we do when retrieving information,
whether it be from the database or from our back end
APIs at the moment.
MARTIN GORNER: And so you wanted to show us a demo--
MUSTAFA SEZGIN: Yep.
MARTIN GORNER: --of one of the flows that you have refactored
using this reactive programming--
MUSTAFA SEZGIN: Yes.
MARTIN GORNER: --in your Android application.
MUSTAFA SEZGIN: That's correct, yeah.
MARTIN GORNER: So let's see the demo.
MUSTAFA SEZGIN: Sure.
There's a number of areas where we've done that
refactoring, but I'll show you one of the screens
where we've done this.
So, for a user who basically wants to sign up, they come
in, we've already got a Google account on here.
So we'll sign in with Google, we accept that.
That logs us in.
And we'll see here, this is our onboard in process where
we're able to actually see a number of different
categories.
For someone who's just signed up, they can basically find
some of their favorite artists, maybe.
So if they like rock, they can go in here and they can see
all the different artists.
MARTIN GORNER: And so this data is something you pull
from your server?
MUSTAFA SEZGIN: That's correct.
MARTIN GORNER: The list of genres and the list of the top
artists in these genres.
What we want to do here is on the device call a network API,
so something that returns data from the SoundCloud APIs.
MUSTAFA SEZGIN: Yep.
MARTIN GORNER: And process those data, get them back on
the menu [INAUDIBLE] and display them.
So if I wanted to do this by hand, because this is a very,
very common problem, doing things asynchronously.
If I wanted to do this by hand using threads and
synchronizing the results, what would be
the amount of work?
MUSTAFA SEZGIN: There is, if you really want to go to very
low level and kind of schedule your own threads and worry
about synchronization, inconcurrency is a very
difficult problem to solve when
you're developing software.
There are frameworks that are available, or components that
are available in the Android SDK, such as AsyncTasks, that
handle this.
But they are quite basic in what they provide.
They do take care of the low level threading concerns, but
when it comes to error handling, or applying
transformations on the data set, or even, I guess,
scheduling, at times as well, it provides either no or very
little functionality with regards to that.
So there's a lot of extra functionality and useful
functionality built into RxJava that, I guess, makes it
more attractive than using some of the built in Android
SDK components.
MARTIN GORNER: So let's see how it works.
MUSTAFA SEZGIN: Sure, absolutely.
MARTIN GORNER: Here we have the first little bit of
psedo-code to understand what will be going on.
This helped me personally understand--
MUSTAFA SEZGIN: Yep.
MARTIN GORNER: --because once we go to the Java code, there
is a little bit of extra syntactic sugar to make this
work in Java.
MUSTAFA SEZGIN: Yep.
MARTIN GORNER: But the basics are actually quite simple.
Can you tell us what is going on?
MUSTAFA SEZGIN: Sure.
So, you could consider that using kind of the publish
subscribe panel, the observable pattern, you have
your data stream, which in the land of RxJava, is your
observable.
You want to observe your data stream, basically.
So the first thing that you need to kind of obviously do
is have an observable data stream.
And the person or, I guess, the component which is
interested in this data stream needs to subscribe to it, and
that's what we see in the first line there.
MARTIN GORNER: So that first line actually launches the
asynchronous processing.
MUSTAFA SEZGIN: Yes.
MARTIN GORNER: You subscribe the observable to an observer,
and basically what you do is that you register this doNext
function, which is a callback--
MUSTAFA SEZGIN: Yep.
MARTIN GORNER: --on your observable.
MUSTAFA SEZGIN: That's correct.
So basically the work itself, very simplistically, the
observable there contains all the logic required to retrieve
your data asynchronously.
As soon as you call subscribe and pass in that doNext
function, RxJava kind of takes care of the rest to launch you
thread and then basically execute you observable, which
is the red line that we see there with the call function.
MARTIN GORNER: And the call function is
something that you define.
So that's your function, you define what
work you want to do--
MUSTAFA SEZGIN: That's correct.
MARTIN GORNER: --then, at the end, you will call that doNext
function, which you have [? in past ?].
MUSTAFA SEZGIN: That's correct.
So once RxJava calls your observable to execute it, you
will do your work and obtain your data, and then you'll
pass your data to the callback function, which is that doNext
function that we have provided there.
MARTIN GORNER: So let's see that with a
real Java code now.
MUSTAFA SEZGIN: Yes.
MARTIN GORNER: So this is how you define an observable.
MUSTAFA SEZGIN: It's very--
because of the wording, a lot of people misuse those or for
one another.
But basically, in this first slide, what we're doing is
we're actually--
a very simplistic example is we want to make a network call
to some back end API.
And so, what we do is we try and be as functional as we can
be in Java, and we create this observable object.
And we talked about that call function, and that is where
you do your work.
MARTIN GORNER: So the client does not make request, that is
your work, your API call.
MUSTAFA SEZGIN: That's correct, yeah.
So you're making an API request there, and you get
back a response.
Now the next lines are where kind of a lot of the magic
happens, in a way.
So, you can see that you passed in the observer, which
is basically that callback function that we were talking
about earlier.
And once you have your data, you pass it to the observer by
calling on next.
And you can do this multiple times if you have a collection
of objects, for example.
You can loop over those and then basically be calling on
next multiple times to provide that
data until it's completed.
And at the end, once you've streamed all your data, you
have to call on complete to signal to the caller that the
stream has ended.
MARTIN GORNER: So let us see what an observer looks like.
MUSTAFA SEZGIN: Sure.
What we're doing here is now that we've created our
observable, the interested party wants to basically
subscribe to the data that's going to come back from that
observable.
And you can see there that, once again, we create a kind
of an anonymous inner class, which is that observer to the
subscribe function.
And it has to implement those three methods there.
The first one, which is I guess the most important one,
is on next function, and that is what will receive the data.
And whatever kind of processing you want to do as a
result of that data, you should be doing in that
function there.
And once you receive-- and, as I mentioned, that can be
called multiple times, executed multiple times--
and once you've completed streaming your data, you need
to call on completed, and that will basically signal to the
observer that the stream has ended, and that there's no
more data to come.
Now, as I mentioned earlier as well, there's built in error
handling into RxJava.
So if an exception gets raised that you didn't catch during
the work function, and why you would retrieve a network I/O
error or something, that exception will automatically
be handled by RxJava, and will be passed through to the on
error handler or callback in your observer.
MARTIN GORNER: That's very handy.
MUSTAFA SEZGIN: It is very hand.
MARTIN GORNER: And so the last issue we have to addresses is
that RxJava is a genetic framework.
MUSTAFA SEZGIN: Yep.
MARTIN GORNER: But on Android, you want your results
delivered on a specific thread,
which is the UI thread.
MUSTAFA SEZGIN: That's correct.
MARTIN GORNER: So how do you do that?
MUSTAFA SEZGIN: So the observable has two methods
that basically we saw in the previous slide.
The first one was--
MARTIN GORNER: Let's go back to it.
MUSTAFA SEZGIN: Yep.
The first one there was a subscribe on.
What that means is that that's where you specify a scheduler
that you want the actual work function to be completed on.
So in this instance, it was making the API call.
But the really cool thing is that the observe on method
there that you see on the observable specifies a
separate scheduler where you can actually specify which
thread the data will be delivered on.
Now, in Android land, whenever you want to update the user
interface on the device, you need to be doing that work on
the main UI thread.
MARTIN GORNER: And so there are a couple more lines of
code to define a scheduler that will
handle the data on the--
MUSTAFA SEZGIN: UI thread.
MARTIN GORNER: --main UI thread.
MUSTAFA SEZGIN: That's correct.
Now, this is very simplistic.
There's a scheduler class within RxJava that you need to
subclass, and it has two abstract schedule methods that
you'll need to implement.
This is a very simplistic implementation of one of them,
but what we do here is basically we specify that
there's basically a handler which runs runables on the
main looper, which is the main UI thread.
MARTIN GORNER: And the main looper is the
main Android UI thread.
MUSTAFA SEZGIN: That's correct.
MARTIN GORNER: That is a call to the Android [INAUDIBLE].
MUSTAFA SEZGIN: This is all mainly Android code, yes, and
this will exist in, like I said, the scheduler that
you'll subclass.
And what this does is it tells RxJava to execute that actio,
the action.call class, or the actual call line that we see
there in the run method, which will deliver those results
that are passed through on next to the observer on the
main UI thread.
MARTIN GORNER: When you are shopping around for a library
like this, have you evaluated other possibilities?
MUSTAFA SEZGIN: In Android, one of the common components
is obviously async task, and some of the other components
that live in the Android SDK.
There are some extra--
for those that are familiar with libraries like Robojuice,
which provide some dependency injection functionality as
well, they extend some of the async task
functionality there as well.
We found with RxJava, in comparison to using some of
these standard libraries or components in the SDKs, is
that it not only takes care of a lot of those low level
concerns, but it provides some extra functionality to take
care of the error handling, as well.
But on top of that, a lot of times, you want to apply
transformations on your data.
There's a lot of built in functionality within RxJava to
apply transformations like filtering or actually
transforming the data itself before being
delivered to the caller.
And on top of that, one really interesting piece of
functionality is that you can actually combine data from
multiple sources.
So if you need to go, for example, to your database, and
you need to go to the API, and then you need to compose the
data set into a single stream of data, RxJava actually has
built in functionality to be able to do that quite easily.
So there's a lot of extra functionality and useful
functionality built into RxJava.
MARTIN GORNER: I hope you will enjoy playing with reactive
programming, and thank you very much, Mustafa--
MUSTAFA SEZGIN: Thank you for having me.
MARTIN GORNER: --for being with us on root access Berlin.
MUSTAFA SEZGIN: Sure.
Thank you.