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