Grokking Reactive User Interfaces: with ReactiveX and FRP MEAP

Transcription

Grokking Reactive User Interfaces: with ReactiveX and FRP MEAP
MEAP Edition
Manning Early Access Program
Grokking Reactive User Interfaces
with ReactiveX and FRP
Version 3
Copyright 2016 Manning Publications
For more information on this and other Manning titles go to
www.manning.com
©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and
other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.
https://forums.manning.com/forums/grokking-reactive-user-interfaces
welcome
Thank you for purchasing the MEAP for Grokking Reactive User Interfaces: With ReactiveX and FRP.
We have many names for the things we love, but what we're witnessing in the programming world
is a change of the mental model of how we build applications. Functional reactive programming, as
some call the change, has recently gained significant traction, especially in the development of user
interfaces, and it's radically changed the playing field.
The transition can be confusing though, and you may be wondering what's the big deal. I mean,
it's just another library, right? This book aims to introduce this new way of thinking about programs
and data that's at the core of FRP. We'll see how to build robust and extensible user interfaces by
structuring them into a chain of data transformations.
To get the most out of the book a basic understanding of mobile UI development is beneficial. You
should also be familiar with traditional object-oriented programming paradigms. The examples we
have are made with Java on Android and the ReactiveX implementation called RxJava. We try to keep
the amount of platform-specific code at a minimum though.
In the first part we take a look at a few examples to get into the mindset of data flows. We always
start from concrete examples and see how FRP helps us to solve them. We'll see a few cases where FRP
solves complex-seeming problems more easily than the old ways of making apps.
The second part of the book introduces the concept of a View Model and how they can be used as
a powerful tool to isolate and unit test any view related business logic without involving the view
itself. We'll also see some more involved examples and how FRP enables us to better manage change
and introduce new features.
The third and last part focuses on higher-level application design concerns and strategies. We'll
look at different architectural approaches and frameworks that work well with FRP thinking. On the
higher abstraction level the effort we put into FRP truly pays off, and that's where we're able to
develop and maintain our applications much better than before.
This is the book I wish I would have had when I first started with FRP two and a half years ago. We
hope it will prove an efficient and inspiring starting point on your journey into a new way of making
apps. In addition to FRP we also love feedback, so please send us any questions, comments or
suggestions in the book’s forum!
— Timo Tuominen
©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and
other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.
https://forums.manning.com/forums/grokking-reactive-user-interfaces
brief contents
Part 1: Core Reactive Programming
1 Introduction to Reactive Programming
2 Networking with Observables
3 Building data processing chains
4 Connecting the user interface networking
5 Advanced RxJava
Part 2: View Models in FRP
6 Basics of View Models
7 Creating our first View Model
8 Expanding existing FRP apps
9 Animations with FRP
10 Making a maps client
Part 3: FRP Architectures
11 Single point of truth: the Store
12 View Model life cycles
13 Networking and stores
14 High-level FRP architectures
15 FRP and Reactive Programming overview
©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and
other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.
https://forums.manning.com/forums/grokking-reactive-user-interfaces
introduction to
reactive programming
1
In this chapter
•
What to expect from this book
•
How to use this book
•
Where does FRP fit amongst other paradigms
•
Why FRP?
•
A look into the toolbox
•
Write code to manipulate UI events
©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and
5
other simple mistakes. These will be cleaned up during production
of the book by copyeditors and proofreaders.
https://forums.manning.com/forums/grokking-reactive-user-interfaces
6
Chapter 1
I Introduction to Reactive programming
Perhaps you picked up this book
because...
1
You heard FRP is the cool thing and you have no idea why.
Functional reactive programming and the various libraries that can be
used with it are the hot topic on many platforms. We will have a look of
what all of this is about, and you can decide fo yourself.
{
2
}
You have tried using FRP libraries but struggled to get the big picture.
Many have used the tools of FRP to solve a particular problem
for which it is very convenient. But what is the big deal about just
another hammer for the job?
{
3
FRP is not one those new buzzwords that are
immediately obvious from reading a blog post. After
reading this chapter you will have a rough idea.
The programming syntax used in FRP is misleading and it is
not easy to see the forest from the trees. This is the book
that teaches you how to think in FRP.
}
You have used FRP and you hate it with a passion.
.. though you are curious to be proven wrong. You might have
inherited an application instead of normal kind of code spaghetti it
now has a special flavor that makes it even harder to digest.
{
While we cannot rewrite the app, we will learn to design
application in sensible and extensible way. You can at least be
reassured there is a way to maintain FRP code.
}
Whatever your reason, we want you to...
• learn through extensive illustations and examples.
• understand a new way of seeing programs.
• figure out where to fit FRP in your day to day programming.
©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and
other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.
https://forums.manning.com/forums/grokking-reactive-user-interfaces
Perhaps you picked up this book because...
Don’t read this book if...
You are very new to programming.
FRP is quite a recent principle in the field of programming, and most
platform in which you would use it have a little friction adapting to it.
It is often not a smoothsailing. Hopefully in the future this will change
and everyone will start their programming journey with FRP.
or
“You just need to get it done.”
Partly because of the aforementioned existing legacy in the field, FRP
requires a little more effort than usual, but yields better maintaibility
and a higher understanding of what your program does. If the quality
of the code is not a concern for you, though, you might be hardpressed
justifying FRP.
Further, its most obvious use cases are in UI development and custom
services with dynamic data, which you might not need to do.
but
If you want to improve yourself as a developer and build beautiful
systems without a limit to their complexity I recommend you to carry
on and give this book a chance. Whether FRP is practical enough to
become mainstream is undecided, but nevertheless it is an amazing tool
to enhance your mental model of how software works.
©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and
other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.
https://forums.manning.com/forums/grokking-reactive-user-interfaces
7
8
Chapter 1
I Introduction to Reactive programming
The benefits of FRP
FRP is not a typical technology B that obviously and immediately
replaces an inferior technology A. It’s more of a way of thinking rather
than a mechnical solution—and that is our ultimate goal. We are
exploring a new way of seeing software.
Regardless, there are benefits to FRP that can be easily identified. While
we don’t expect you to buy into them without reading the proof, here
are a few to get your curiosity:
1. Testability with unit tests
Partly due to its functional programming roots, in FRP we strive to
isolate business logic into its own section. With OOP the problem is
often that some important code is hidden into views and other platform
specific components, making it difficult to exhaustively capture the
most crucial bits in the tests.
If done right, in FRP we can in fact test everything. The business logic
will be pure code and fully isolated from any platform specific classes.
2. Revealed obscure issues
Building an FRP program can be tricky, but once it is ready, it is
reasonably simple to trace bugs and problems. More often than not,
a bug is actually an unimplemented behaviour that can be explicitly
added. It is no longer a WTF, but instead a “I did not think of that!”.
In addion, edge cases are captured better, since programs exhibit less
heuristic behaviour: writing a code that “might” work and crossing
your fingers. In FRP crossing your fingers is pointless, since you already
know if it is going to work or not. When dealing with a compiled
language such as Java, usually if it compiles it works.
3. Handling of asynchronous operations
Sometimes the asynchronous handling is listed as the first benefit of
FRP, and it certainly is a major one. The tradional ways of programming
make the handling of asynchronous operations a special case, which is
often a trisky one. In FRP, however, asynchronous is the standard. It is
the synchronous execution that is the exception!
©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and
other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.
https://forums.manning.com/forums/grokking-reactive-user-interfaces
The benefits of FRP
What do you need to know before we
start?
With a suitable library FRP concepts can be applied to almost any
platform and language. However, we need to pick one, and we pick Java
as our language and Android as the platform.
This is not a book about Android development, though, so we will
not go into details. What you need to know is it has widgets and
components, much like any other UI framework you have worked with.
• vhave a basic understand of user interface development and the
challenges it usually poses.
• be able to read basic Java code, including lambdas which were
introduced in Java 8. (On the next page you can find and introduction
to lambdas, in case you have not countered them before.)
You don’t need to ...
• be an expert in object oriented programming patterns.
• have previous experience in traditional functional programming
(though it helps).
Java 8 Streams
While we will make extensive use of Java 8 lambdas, we do not touch
other features that were introduced. In specific Java 8 Streams are not
related to any streams we may or may not be talking about in this books.
©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and
other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.
https://forums.manning.com/forums/grokking-reactive-user-interfaces
9
10
Chapter 1
I Introduction to Reactive programming
Deep dive into FRP: Live search
Screen shot of
Google Maps web
application doing a
search
To get a quick and dirty idea of what FRP is capable of let us have a
look at an example: live search based on user input in a text field. You
start typing in the text field and google helpfully shows you suggestions
without needing to press a search button.
In short, we want to trigger a search through a network API and show
results based on the text user has written so far. However, we only want
to do so when the user has written a minimum of 3 characters and has
momentarily paused writing.
Conditions for triggering search:
1
Ignore input shorter than 3 characters.
2
Only perform a search when the user has not been typing for
150 milliseconds.
©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and
other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.
https://forums.manning.com/forums/grokking-reactive-user-interfaces
Deep dive into FRP: Live search
A quick implementation
The first task is to establish a basic connection between the editable
text input and the list that renders the search results. At this point we
are not interested in the details of the UI implementation but instead
how they interact. Later in the book we will also see how to make UI
components with FRP.
As we would typically do, we assign a listener to the text input that is
executed when ever the user edits the text. On the other hand, we have
a function that updates the search results in the background. Let us call
this function updateSearchResults.
This piece of pseudo code would happily update the search results every
textInput.setOnChangeListener(text -> {
updateSearchResults(text);
});
time the text changes. No FRP here.
The first condition for text length is equally trivial to fulfil:
However, this is where our luck ends. What should we do about the
textInput.setOnChangeListener(text -> {
if (text.length() >= 3) {
updateSearchResults(text);
}
});
second one? The code in the event handler executes immediately, or
in other words synchronously, but our condition is dependent on time
passed after it was called.
While we could start making timers in the listener callback, it smells
like that they would hold at best “passable” beauty standards. Instead,
we can shift our thinking a bit and solve the problem with FRP.
The next few pages will lead to a solution the core of which is not more
than 4 lines.
©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and
other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.
https://forums.manning.com/forums/grokking-reactive-user-interfaces
11
12
Chapter 1
I Introduction to Reactive programming
Text input as a producer of data
As often is, we first have to take a step back and reshape how we view
the problem. We have two sides: the text input that produces text values
and a function that we call with those values to retrieve the results.
How can data be “produced”?
In this case when we talk about producing data, it simply means that the
text input has received user input and how holds a different value than
previously. It subsequently sends an event to all its listeners, informing
of the state change. From the point of view of an individual listener, the
text input just produced a new value of type String and we should do
something with it.
The refresh function can also be called the consumer of the data, or the
subscriber.
This is the produced string value
User types the letter m
m
“m”
updateSearchResults(”m”)
Text input as a
producer of String
data
User types the letter c
mc
“mc”
updateSearchResults(”mc”)
User types the letter d
mcd
“mcd”
updateSearchResults(”mcd”)
In the code we had before, the text input would give the new string
value text to the event listener, which in turn would give it to the
updateSearchResults function.
Since the user is not typing at infinite speed, these values would arrive
at different times. This is how typing into a text input works.
©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and
other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.
https://forums.manning.com/forums/grokking-reactive-user-interfaces
The Publish-Subscribe pattern
The Publish-Subscribe pattern
Time to simplify!
For our logic we can actually forget about the text input and just take
the values it produces as the user types. Here they are added with times
elapsed:
0ms
“m”
updateSearchResults(”m”)
100ms
“mc”
updateSearchResults(”mc”)
250ms
“mcd”
updateSearchResults(”mcd”)
Every time the user presses a key, we get a new string that the text input
sends us. The text input is producing, or publishing, string values.
In fact, we have ourselves a stream of data over time.
time
0ms
“m”
updateSearchResults(”m”)
100ms
“mc”
updateSearchResults(”mc”)
250ms
“mcd”
updateSearchResults(”mcd”)
We call this a marble diagram - for the fact that the data items are
displayed as flat marbles. Notice that our code still has not changed, we
are simply interpreting it in a different way!
©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and
other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.
https://forums.manning.com/forums/grokking-reactive-user-interfaces
13
14
Chapter 1
I Introduction to Reactive programming
Text input as an Observable
We already saw that a text input can be considered a producer of
string values over time. A producer like this is sometimes called an
Observable, since the values it produces can be observed.
We will now take into use an FRP library to formalise the abstraction.
What we want to do is wrap the text input into an observable essentially hiding the implementation and making it a pure producer of
data.
RxTextView.textChanges(textInput)
The counterpart of an observable is a subscriber, and it can be simply
be a function. In our case the updateSearchResults is indeed the
subscriber.
RxTextView.textChanges(textInput)
.subscribe(this::updateSearchResults);
Create an
observable based
on the text input
change events
Subscribe to the
observable created
on the former line
Interestingly enough, we can still use the same diagrams as before.
updateSearchResults is called as before, and in fact only the binding
logic between the source of data (text input component) and the
handler of the data (updateSearchResults) has been changed to use
FRP. Right now, though, there is no difference yet.
This column now
becomes the
observable itself
time
0ms
“m”
updateSearchResults(”m”)
100ms
“mc”
updateSearchResults(”mc”)
250ms
“mcd”
updateSearchResults(”mcd”)
©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and
other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.
https://forums.manning.com/forums/grokking-reactive-user-interfaces
The Reactive Stream
The Reactive Stream
Now that we everything set up we can start with real FRP. Everything
we do is based on the kind of publisher-subscriber pattern we
described. There are producers of data and the consumers: what
happens in between is the FRP logic.
With the decoupling of observables and subscribers we have created a
convenient situation for our logic. The subscriber does not know where
and when the data comes from, or how many pieces of it.
We can therefore manipulate the data as it is on the way to the
subscriber. For instance, we can disqualify data items based on certain
conditions, such as whether the string is at least 3 characters long. This
is called filtering the stream.
What does filtering a stream mean?
Let us you think about the data stream as a literal stream with fish of
different sizes traveling in it. They come at different times as the water
flows. A filter in this set up might be one that catches only fish that are
large enough, letting the small ones through. We are filtering the passing
fish based on their characteristics - in this example the physical size.
Essentially we create a new stream based on the original one, but only
on where the strings too short are missing. The result is the same as the
if-clause we had on the quick implementation on page 9.
original
observable
filtered
observable
“m”
The string is too
short, do not let
it go forward, i. e.
filter it
“mc”
“mcd”
“mcd”
updateSearchResults(”mcd”)
©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and
other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.
https://forums.manning.com/forums/grokking-reactive-user-interfaces
15
16
Chapter 1
I Introduction to Reactive programming
Conveniently most FRP libraries have a method to perform filtering. It
works so that we give it a function that gets the data object to evaluate,
and either lets it pass (returns true), or filters it out (returns false). The
filtered values will simply disappear and never reach the subscriber (in
our case updateSearchResults function).
To refresh your memory, here is the initial implementation we made a
few pages back:
textInput.setOnChangeListener(text -> {
if (text.length() >= 3) {
updateSearchResults(text);
}
});
And now we can write the same in FRP. Notice that this code calls the
updateSearchResults exactly the same as the previous listing.
RxTextView.textChanges(textInput)
.filter(text -> text.length() >= 3)
.subscribe(this::updateSearchResults);
Done! Great! It works! ..the same as before.
Why the effort, you might ask? That brings us to our next topic..
Bending time
We have finally reached the point where FRP gets interesting - and
incredibly helpful for the second condition.
Our little observable system is now based on data items produced (or
emitted) by an observable, and data items received by a subscriber.
With the filter function we already saw that these are not necessarily the
same data items. The subscriber does not know what to expect, so we
can simply delete some of them on the way.
A less obvious aspect is since a subscriber does not know anything
about where the data comes from a data item does not need to arrive at
the same time it was sent.
©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and
other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.
https://forums.manning.com/forums/grokking-reactive-user-interfaces
Bending time
17
It turns out with an FRP library we can easily manipulate time
relationships of data emitted and data consumed. We could, for
instance, delay all data items by 50 milliseconds. In our example it
would mean that the search queries are always made 50ms later.
It does not sound very useful, but this is how it would look like in our
marble diagram (without filtering this time):
original
observable
delayed
observable
“m”
50ms
“m”
updateSearchResults(”mcd”)
“mc”
updateSearchResults(”mcd”)
“mcd”
updateSearchResults(”mcd”)
“mc”
“mcd”
For instance, the first marble could be described as such:
1. User types an “m” in the text input
2. The text input observable emits the string “m” into the stream
3. Because of the delay operation the FRP system makes the marble wait
for 50ms
4. After 50ms has passed, the marble can continue its journey and in this
case end up being consumed by the updateSearchResults function.
As promised, of course, the code is trivial. We tell our FRP system
to delay all data items emitted from the source by 50ms, effectively
creating a new observable that is a bit late.
RxTextView.textChanges(textInput)
.delay(50, TimeUnit.MILLISECONDS)
.subscribe(this::updateSearchResults);
This is the
operator that
delays everything
it gets its hands on
©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and
other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.
https://forums.manning.com/forums/grokking-reactive-user-interfaces
18
Chapter 1
I Introduction to Reactive programming
Can I use a delay with a negative number?
In case you had your hopes up, unfortunately delay operator does not
work with negative values, and thus cannot receive data items from the
future. There have been theories about time travel, and currently it is
deemed possible, but only in case another end of a portal is set up in the
future “first”. It seems this has not yet happened.
Bending time in our benefit
Delaying everything is not usually desired behaviour. However, there
was a seed of a solution there. If we look at our second condition again:
Only perform a search when the user has not been typing for 150
milliseconds.
Since emitting an item to the subscriber triggers the search, this
condition would seem to imply that we indeed have to send the last
item with 150ms delay. But only in case no other item was emitted during
that time.
If we received another item right after it would mean the user is still
typing, and we want to let them finish.
Effectively what we have is a bus stop: The bus will only leave once
everyone is on the bus and the driver has managed to close the doors.
As long as there is still someone coming the doors cannot close and the
departure will not happen.
The time we have between the latest person stepping in and the doors
closing is 150ms. As long as the user has not stopped typing for long
enough the updateSearchResults bus has to wait.
©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and
other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.
https://forums.manning.com/forums/grokking-reactive-user-interfaces
Bending time in our benefit
19
Debounce: The Bus Stop Operator
In this chapter we are going to cut it short and get to the more precise
details of the operators laters. We are lucky to find out that what we
described on the last page is actually a reasonably common problem in
reactive programming and there already exists an operator for it. It is
called debounce:
Debounce: only emit an item from an Observable if
a particular timespan has passed without it emitting
another item.
- ReactiveX Wiki
This may sound a bit abstract, but it’s just how the wiki is written.
Often seeing an example of what you can do with the operator makes it
clearer. However, there might be more than one use for each, which is
why the wiki is kept on a high level.
In our case we already have an example, so let’s next see how it works
from the user’s point of view:
1
User starts typing “m” in the search box
original
observable
debounced
observable
“m”
150ms
“mcd”
The user pressed the “m”
key and we receive the
item in our observable.
What debounce does,
it puts the “m” in store
as a potential candicate,
but waits for 150ms
before confirming it
indeed should be let go
forward.
candidate
©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and
other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.
https://forums.manning.com/forums/grokking-reactive-user-interfaces
20
Chapter 1
2
I Introduction to Reactive programming
User types “c” immediately afterwards
original
observable
debounced
observable
“m”
150ms
“mc”
User continues typing
before 150ms has
passed, which makes
the previous candidate
invalid! Instead
debounce stores “mc” as
the new candidate, and
resets the 150ms timer.
“mc”
the new candidate
3
User stops typing
original
observable
debounced
observable
“m”
150ms
“mc”
“mc”
Finally the user stops
typing for long enough
for the 150ms timer to
trigger. We can now send
out the candicate we had,
this time “mc”.
Subsequent items will
not affect it anymore, as
it is already out there.
update
©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and
other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.
https://forums.manning.com/forums/grokking-reactive-user-interfaces
Bending time in our benefit
21
The code
When we apply the debounce to our previous code we actually get the
final solution:
RxTextView.textChanges(textInput)
.filter(text -> text.length() >= 3)
.debounce(150, TimeUnit.MILLISECONDS)
.subscribe(this::updateSearchResults);
This really does conform to the conditions originally imposed on us:
it filters our searches less than 3 characters and wait until user has not
typed for 150ms before sending a search request.
The entire picture looks like this:
original
observable
filtered
observable
debounced
observable
“m”
“mc”
“mcd”
“mcd”
“mcdo”
“mcdo”
150ms
“mcdo”
“mcd”
update
“mcd”
©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and
other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.
https://forums.manning.com/forums/grokking-reactive-user-interfaces
22
Chapter 1
I Introduction to Reactive programming
Putting it into Android
We have so far just seen code without specifying where to exactly
put it in our tradinational Android application. We have a couple of
requirements here:
1. Run after UI is created
2. Run only once for the created UI
Seemingly the most obvious place would appear to be either Activity
onCreate on Fragment onViewCreated. Either will do—in this case we
will use an Activity, since we only our UI is not very complex.
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final EditText textInput =
(EditText) findViewById(R.id.text_input);
RxTextView.textChanges(textInput)
.filter(text -> text.length() >= 3)
.debounce(150, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::updateSearchResults);
}
}
private void updateSearchResults(String search) {
...
}
We added a thread change in the middle, since we need to be sure that
any operations that manipulate the UI are executed on the main thread.
In this case the FRP system will automatically switch the thread to a
background one in order to not block the execution while we wait for
more input.
We will cover thread changes more extensively in
the later chapters, but usually it is enough to call
.observeOn(AndroidSchedulers.mainThread()) just before doing
a UI operation in the next step. This call will change the thread for
anything downstream, meaning the steps that come after it are in the
thread it defined.
©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and
other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.
https://forums.manning.com/forums/grokking-reactive-user-interfaces
Coffee Break
23
Coffee Break
Try to make your own application where you
use other kinds of input components that the
RxBinding library has. They all start with Rx, for instance:
• RxCompoundButton.checkedChanges
• RxRadioGroup.checkedChanges
These two return a boolean instead of a string.
RxCompoundButton.checkedChanges(compoundButton)
.subscribe(isChecked -> {
myLabel.setText(
isChecked ? “box checked!” : “:(“
);
});
This is a special case where
are not obliged to use the
observeOn. We know that the
observable here is on main
thread because it originates
from the UI.
When looking at the functions RxTextView offers, we
can also see ones that do not return observables. These
are functions that you can invoke on a TextView, such as
Action1<CharSequence> text(TextView). We can use them
instead of the lambda syntax, if we want to. It is up to you which
one you prefer, but we will continue using lambdas for brevity.
Exercise:
Make an EditText and a TextView. Have the TextView say “Text too
long” after user has typed more than 7 characters.
©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and
other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.
https://forums.manning.com/forums/grokking-reactive-user-interfaces
24
Chapter 1
I Introduction to Reactive programming
Principles of Functional Reactive
Programming
We have already seen a snippet of FRP in action. This was just
the tip of the iceberg, but we are starting to see the pattern here
already:
• Program is seen as a data processing system—something goes in
and something comes out. It might come out as text change or an
animation on the screen.
• Data processing is done with small functions that take an input and
produce an output (or an effect, such as debounce). An FRP library is
the glue between these functions, giving the data from the previous
function to the next.
• Every function is considered asynchronous. Running a function takes
time. It might be just a millisecond or two, but there no such thing
as “instant”. We therefore only declare what should happen after a
function has been executed but we do not hang around waiting for it.
The application becomes a big pipeline of different points of inputs and
outputs. What happens in between is the isolated FRP logic. It models
how we can calculate the output based on our inputs.
network
Application
user
file system
user interface
network
Asynchronous
FRP logic
database
In out example the input was the user typing into the EditText. We
wrapped the input into an observable and pushed the generated data
into the asynchronous FRP logic. The output in this case was shown in
the updateSearchResults.
©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and
other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.
https://forums.manning.com/forums/grokking-reactive-user-interfaces
Summary
Summary
Wow! That was almost 20 pages to write 5 lines. You are probably
wondering if it was really necessary.. I mean, could we not just check
stackoverflow and copy the snippet?
The answer is yes and no. You can check stackoverflow and copy the
snippet, if you know you how to formulate the question in the FRP terms.
Many problems do indeed become almost trivial once they are framed
in the right way.
After 2 years of doing FRP I find phrasing of the question to be 90%
of the work. Often your problem is not as unique as it first seems, and
there might already be an operator that exists for it. In a few special
cases the actual problem is indeed difficult, and we will learn to
recognize and solve those problems later in the book.
However, most of the time we will be learning to ask the right question.
©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and
other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.
https://forums.manning.com/forums/grokking-reactive-user-interfaces
25