You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: Part 2 - Sequence Basics/1. Creating a sequence.md
+21-21Lines changed: 21 additions & 21 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,10 +1,10 @@
1
1
# PART 2 - Sequence basics
2
2
3
-
Now that you understand what Rx is in general, it is time to start creating and manipulating sequences. The original implementation of manipulating sequences was based on C#'s LINQ, which in turn came from functional programming. Knowledge about either will not be assumed, but it would make the learning process a lot simpler. Following the original www.introtorx.com, we too will divide operations into themes that generally go from the simpler to the more advanced. Most Rx operators manipulate existing sequences. But first, we will see how to create an observable to begin with.
3
+
Now that you understand what Rx is in general, it is time to start creating and manipulating sequences. The original implementation of manipulating sequences was based on C#'s LINQ, which in turn was inspired from functional programming. Knowledge about either isn't necessary, but it would make the learning process a lot easier for the reader. Following the original www.introtorx.com, we too will divide operations into themes that generally go from the simpler to the more advanced. Most Rx operators manipulate existing sequences. But first, we will see how to create an `Observable` to begin with.
4
4
5
5
# Creating a sequence
6
6
7
-
In previous examples we used `Subject`s and manually pushed values into them to create an sequence. We used that sequence to demonstrate some key concepts and the first an most important Rx method, `subscribe`. We will now see tidier ways to create observables.
7
+
In previous examples we used `Subject`s and manually pushed values into them to create an sequence. We used that sequence to demonstrate some key concepts and the first and most important Rx method, `subscribe`. In most cases, subjects are not the best way to create a new `Observable`. We will now see tidier ways to create observable sequences.
`defer` doesn't define a new kind of observable, but allows you to declare that a source observable should be created when a subscriber arrives. Consider how you would create an observable that returns the current time and terminates. You are emitting a single value, so it sounds like a case for `just`.
85
+
`defer` doesn't define a new kind of observable, but allows you to declare how a source observable should be created every time a subscriber arrives. Consider how you would create an observable that returns the current time and terminates. You are emitting a single value, so it sounds like a case for `just`.
86
86
87
87
```java
88
88
Observable<Long> now =Observable.just(System.currentTimeMillis());
@@ -97,7 +97,7 @@ Output
97
97
1431443908375
98
98
```
99
99
100
-
Notice how the two subscribers, 1 second apart, see the same time. That is because the value for the time is aquired once: when execution reaches `just`. What you want is for the time to be aquired when a subscriber asks for it by subscribing. `defer` takes a function that will executed to create the observable. The function will be executed for every subscription.
100
+
Notice how the two subscribers, 1 second apart, see the same time. That is because the value for the time is aquired once: when execution reaches `just`. What you want is for the time to be aquired when a subscriber asks for it by subscribing. `defer` takes a function that will executed to create and return the `Observable`. The `Observable` returned by the function is also the `Observable` returned by `defer`. The important thing here is that this function will be executed again for every new subscription.
101
101
102
102
```java
103
103
Observable<Long> now =Observable.defer(() ->
@@ -115,13 +115,13 @@ Output
115
115
116
116
### Observable.create
117
117
118
-
`create` is a very versatile function for creating observables. Let have a look at the signature.
118
+
`create` is a very powerful function for creating observables. Let have a look at the signature.
The `Observable.OnSubscribe<T>` is simpler than it looks. It is basically a function that takes an `Subscriber` for type `T`. In that function, we can manually determine the event calls to that subscriber.
124
+
The `Observable.OnSubscribe<T>` is simpler than it looks. It is basically a function that takes an `Subscriber<T>` for type `T`. Inside it we can manually determine the events that are pushed to the subscriber.
When someone subscribes to your observable, the corresponding subscriber instance is passed to your function. Your code will be executed, resulting in values being pushed to your new subscriber. Note that you have to call `onCompleted` in the end by yourself, if you want the sequence to signal its completion.
143
+
When someone subscribes to the observable (here: `values`), the corresponding `Subscriber` instance is passed to your function. As the code is executed, values are being pushed to the subscriber. Note that you have to call `onCompleted` in the end by yourself, if you want the sequence to signal its completion.
144
144
145
-
This method should be your preferred way of creating a custom observable, when none of the existing shorthands serve your purpose. The code is similar to how we created a `Subject` and pushed values to it, but there are a few important differences. First of all, the source of the events is neatly encapsulated and separated from unrelated code. Secondly, `Subject`s carry dangers that are not obvious. For one thing, with a `Subject` you are managing state, as anyone with access to the instance can push values into it and alter the sequence.
145
+
This method should be your preferred way of creating a custom observable, when none of the existing shorthands serve your purpose. The code is similar to how we created a `Subject` and pushed values to it, but there are a few important differences. First of all, the source of the events is neatly encapsulated and separated from unrelated code. Secondly, `Subject`s carry dangers that are not obvious: with a `Subject` you are managing state, and anyone with access to the instance can push values into it and alter the sequence. We will see more about this issue later on.
146
146
147
-
Another key difference is that the code is executed lazily, when and if an observer subscribes. In the example above, the code is run _not_ when the observable is created (because there is no instance of `Subscriber` yet), but each time `subscribe` is called. That means that every value is generated again for each subscriber, similar to `ReplaySubject`. However, if we had used a `ReplaySubject`, and the creation method was time-consuming, that would block the thread that executes the creation. You'd have to manually create a new thread to push values into the `Subject`. We're not presenting Rx's methods for concurrency yet, but there are convenient ways to make the execution of the onSubscribe function concurrently.
147
+
Another key difference to using subjects is that the code is executed lazily, when and if an observer subscribes. In the example above, the code is run _not_ when the observable is created (because there is no `Subscriber` yet), but each time `subscribe` is called. This means that every value is generated again for each subscriber, similar to `ReplaySubject`. The end result is similar to a `ReplaySubject`, except that no caching takes place. However, if we had used a `ReplaySubject`, and the creation method was time-consuming, that would block the thread that executes the creation. You'd have to manually create a new thread to push values into the `Subject`. We're not presenting Rx's methods for concurrency yet, but there are convenient ways to make the execution of the `onSubscribe` function concurrently.
148
148
149
-
You may have already noticed that you can trivially implement any of the previous observables using `Observable.create`. In fact, our example is essentially an`Observable.just("hello")`.
149
+
You may have already noticed that you can trivially implement any of the previous observables using `Observable.create`. In fact, our example for `create`is equivalent to`Observable.just("hello")`.
150
150
151
151
## Functional unfolds
152
152
153
-
In functional programming it is common to create sequences of unrestricted or infinite length.
153
+
In functional programming it is common to create sequences of unrestricted or infinite length. RxJava has factory methods that create such sequences.
154
154
155
155
### Observable.range
156
156
157
-
A straight forward and familiar methods. It emits the specified range of integers.
157
+
A straight forward and familiar method to any functional programmer. It emits the specified range of integers.
This sequence will not terminate until we unsubscribe.
189
189
190
-
We should note why the blocking read at the end is necessary. Without it, the program terminates without printing something. That's because our operations are non-blocking: we create an observable that _will_ emit values, then we register the actions to execute if and when values arrive. None of that is blocking and the program proceeds to terminate. The timer that produces the ticks runs on its own thread. On the chapter about scheduling and threading we will see more about the threads on which actions run and how to manipulate that.
190
+
We should note why the blocking read at the end is necessary. Without it, the program terminates without printing something. That's because our operations are non-blocking: we create an observable that will emit values_over time_, then we register the actions to execute if and when values arrive. None of that is blocking and the main thread proceeds to terminate. The timer that produces the ticks runs on its own thread, which does not prevent the JVM from terminating, killing the timer with it.
191
191
192
192
### Observable.timer
193
193
@@ -230,7 +230,7 @@ The example above waits 2 seconds, then starts counting every 1 second.
230
230
231
231
## Transitioning into Observable
232
232
233
-
There are well established tools for dealing with sequences, collections and asychronous events. Other libraries that you use may not be directly compatible with Rx. Here we will discuss ways to turn their output into input for your Rx code.
233
+
There are well established tools for dealing with sequences, collections and asychronous events, which may not be directly compatible with Rx. Here we will discuss ways to turn their output into input for your Rx code.
234
234
235
235
If you are using an asynchonous tool that uses event handlers, like JavaFX, you can use `Observable.create` to turn the streams into an observable
Depending on what the event is, the event type (here `ActionEvent`) may be meaningful enough to be type of your sequence. Very often you will want something else, like the contents of a field. The place to get the value is in the handler, while the GUI thread is blocked by the handler and the field value is relevant. There is no guarantee what the value will be by the time the value reaches your `Subscriber`. On the other hand, a value moving though an observable should remain unchanged.
247
+
Depending on what the event is, the event type (here `ActionEvent`) may be meaningful enough to be the type of your sequence. Very often you will want something else, like the contents of a field. The place to get the value is in the handler, while the GUI thread is blocked by the handler and the field value is relevant. There is no guarantee what the value will be by the time the value reaches the final `Subscriber`. On the other hand, a value moving though an observable should remain unchanged, if the pipeline is properly implemented.
248
248
249
249
## Observable.from
250
250
251
-
Much like most of the functions we've seen so far, you can turn any common input into an Rx observable with `create`. There are several shorthands for converting common types of input.
251
+
Much like most of the functions we've seen so far, you can turn any kind of input into an Rx observable with `create`. There are several shorthands for converting common types of input.
252
252
253
-
`Future`s are part of the Java framework and you may come across them while using frameworks that use concurrency. They are a less powerful concept for concurrency than Rx, since they only return one value. You can turn them into observables to consume.
253
+
`Future`s are part of the Java framework and you may come across them while using frameworks that use concurrency. They are a less powerful concept for concurrency than Rx, since they only return one value. Naturally, you'd like to them into observables.
254
254
255
255
```java
256
256
FutureTask<Integer> f =newFutureTask<Integer>(() -> {
If the `Future` has not completed the specified amount of time, the observable will ignore it and fail with a `TimeoutException`.
284
284
285
-
You can also turn any collection into an observable using the overloads of `Observable.from` that take arrays and iterables. This will result in every item in the collection to be emitted and then the observable will terminate.
285
+
You can also turn any collection into an observable using the overloads of `Observable.from` that take arrays and iterables. This will result in every item in the collection being emitted and then a final onCompleted event.
286
286
287
287
```java
288
288
Integer[] is = {1,2,3};
@@ -302,7 +302,7 @@ Received: 3
302
302
Completed
303
303
```
304
304
305
-
`Observable` is not interchangeable with `Iterable` or `Stream`. `Observable`s are push-based. i.e. the first call to `onNext` causes the stack to execute all the way to the subscriber method (unless specified otherwise). The others are pull-based, which means that values are requested as soon as possible and execution blocks until the result is returned.
305
+
`Observable` is not interchangeable with `Iterable` or `Stream`. `Observable`s are push-based. i.e. the call to `onNext` causes the stack of handlers to execute all the way to the final subscriber method (unless specified otherwise). The other model are pull-based, which means that values are requested as soon as possible and execution blocks until the result is returned.
0 commit comments