Skip to content

Commit 5f4acdd

Browse files
committed
2.1 Reworked chapter
1 parent c92c8a0 commit 5f4acdd

File tree

1 file changed

+21
-21
lines changed

1 file changed

+21
-21
lines changed

Part 2 - Sequence Basics/1. Creating a sequence.md

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
# PART 2 - Sequence basics
22

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.
44

55
# Creating a sequence
66

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.
88

99
## Simple factory methods
1010

@@ -62,7 +62,7 @@ Subscription subscription = values.subscribe(
6262

6363
The above code will print nothing. Note that this doesn't mean that the program is blocking. In fact, it will terminate immediately.
6464

65-
### Observable.throw
65+
### Observable.error
6666

6767
This observable will emit a single error event and terminate.
6868

@@ -82,7 +82,7 @@ Error: java.lang.Exception: Oops
8282

8383
### Observable.defer
8484

85-
`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`.
8686

8787
```java
8888
Observable<Long> now = Observable.just(System.currentTimeMillis());
@@ -97,7 +97,7 @@ Output
9797
1431443908375
9898
```
9999

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.
101101

102102
```java
103103
Observable<Long> now = Observable.defer(() ->
@@ -115,13 +115,13 @@ Output
115115

116116
### Observable.create
117117

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.
119119

120120
```java
121121
static <T> Observable<T> create(Observable.OnSubscribe<T> f)
122122
```
123123

124-
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.
125125

126126
```java
127127
Observable<String> values = Observable.create(o -> {
@@ -140,21 +140,21 @@ Received: Hello
140140
Completed
141141
```
142142

143-
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.
144144

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.
146146

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.
148148

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")`.
150150

151151
## Functional unfolds
152152

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.
154154

155155
### Observable.range
156156

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.
158158

159159
```java
160160
Observable<Integer> values = Observable.range(10, 15);
@@ -164,7 +164,7 @@ The example emits the values from 10 to 24 in sequence.
164164

165165
### Observable.interval
166166

167-
This function will create an _infinite_ sequence of ticks, spaced out between them by the specified time span.
167+
This function will create an _infinite_ sequence of ticks, separated by the specified time duration.
168168

169169
```java
170170
Observable<Long> values = Observable.interval(1000, TimeUnit.MILLISECONDS);
@@ -187,7 +187,7 @@ Received: 3
187187

188188
This sequence will not terminate until we unsubscribe.
189189

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.
191191

192192
### Observable.timer
193193

@@ -230,7 +230,7 @@ The example above waits 2 seconds, then starts counting every 1 second.
230230

231231
## Transitioning into Observable
232232

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.
234234

235235
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
236236

@@ -244,13 +244,13 @@ Observable<ActionEvent> events = Observable.create(o -> {
244244
})
245245
```
246246

247-
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.
248248

249249
## Observable.from
250250

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.
252252

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.
254254

255255
```java
256256
FutureTask<Integer> f = new FutureTask<Integer>(() -> {
@@ -282,7 +282,7 @@ Observable<Integer> values = Observable.from(f, 1000, TimeUnit.MILLISECONDS);
282282
```
283283
If the `Future` has not completed the specified amount of time, the observable will ignore it and fail with a `TimeoutException`.
284284

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.
286286

287287
```java
288288
Integer[] is = {1,2,3};
@@ -302,7 +302,7 @@ Received: 3
302302
Completed
303303
```
304304

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.
306306

307307
#### Continue reading
308308

0 commit comments

Comments
 (0)