Skip to content
This repository was archived by the owner on May 17, 2023. It is now read-only.

Commit 635cb1c

Browse files
committed
Small edits & updates in the text of coroutines hands-on
1 parent f5f3000 commit 635cb1c

File tree

8 files changed

+28
-35
lines changed

8 files changed

+28
-35
lines changed

Introduction to Coroutines and Channels/01_Introduction.md

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,10 @@ by Roman Elizarov at KotlinConf.
2525

2626
### Set-up
2727

28-
We'll need one of the latest versions of IntelliJ IDEA, so any version from 2018.1 onwards.
29-
You can download the latest free community version [here](https://www.jetbrains.com/idea/download/).
28+
We'll need IntelliJ IDEA; you can download the latest free community version [here](https://www.jetbrains.com/idea/download/).
3029

31-
Make sure version 1.3 of the Kotlin plugin is installed.
32-
To update the Kotlin plugin, use `Tools | Kotlin | Configure Kotlin Plugin Updates`.
30+
Make sure version 1.4 of the Kotlin plugin is installed.
31+
To update the Kotlin plugin, use `Tools | Kotlin | Configure Kotlin Plugin Updates`.
3332

3433
### Downloading project
3534

@@ -43,13 +42,9 @@ and specifying the project path:
4342
$ git clone http://github.com/kotlin-hands-on/intro-coroutines
4443
```
4544

46-
Note that the project includes the `solutions` branch, so it is possible to use the `Compare with branch...`
45+
The project includes the `solutions` branch, so it is possible to use the `Compare with branch...`
4746
action to compare your solution with the proposed one.
4847

49-
Alternatively, you can [download the project](http://github.com/kotlin-hands-on/intro-coroutines/archive/master.zip) directly
50-
(but only the `main` branch).
51-
52-
5348
### Generating GitHub developer token
5449

5550
We'll be using GitHub API.

Introduction to Coroutines and Channels/02_BlockingRequest.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,9 @@ The resulting list should be sorted in descending order according to the number
116116
#### Task
117117

118118
Open `src/tasks/Aggregation.kt` and implement `List<User>.aggregate()` function.
119-
[The corresponding test file](https://www.jetbrains.com/help/idea/navigating-between-test-and-test-subject.html)
120-
shows an example of the expected result.
119+
The corresponding test file `test/tasks/AggregationKtTest.kt` shows an example of the expected result.
120+
You can jump between the source code and the test class automatically [using IntelliJ IDEA
121+
shortcut](https://www.jetbrains.com/help/idea/create-tests.html#test-code-navigation).
121122

122123
After implementing this task, the resulting list for `Kotlin` organization should be similar to the following:
123124

Introduction to Coroutines and Channels/04_Suspend.md

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Using suspend functions
22

3-
Retrofit recently added native support for coroutines, and we're going to use it.
3+
Retrofit provides native support for coroutines, and we're going to use it.
44
Instead of returning `Call<List<Repo>>`, we now define our API call as a `suspend` function:
55

66
```kotlin
@@ -15,9 +15,6 @@ interface GitHubService {
1515
The main idea behind it is that when we use a `suspend` function to perform a request, the underlying thread isn't blocked.
1616
We'll discuss how exactly it works a bit later.
1717

18-
To make use of this functionality, we need the latest version of the Retrofit library.
19-
For this tutorial, we don't need to change anything; the right version is already specified in the project dependencies.
20-
2118
Note that now `getOrgRepos` returns the result directly instead of returning a `Call`.
2219
If the result is unsuccessful, an exception is thrown.
2320

@@ -46,12 +43,12 @@ interface GitHubService {
4643

4744
The task is to change the code of the function loading contributors to make use of these new `suspend` functions.
4845

49-
However, a `suspend` function can't be called everywhere,
46+
A `suspend` function can't be called everywhere,
5047
if it is called from `loadContributorsBlocking`, there will be an error:
5148
"Suspend function 'getOrgRepos' should only be called from a coroutine or another suspend function".
5249
So, we need to mark our new version of the `loadContributors` function as `suspend` in order to use this new API.
5350

54-
Please now do the following task, and right after that we'll discuss how `suspend` functions actually work and how
51+
Please now do the following task, and right after that we'll discuss how `suspend` functions work and how
5552
they are different from regular ones.
5653
We'll also see how to call a `suspend` function from a non-suspending one.
5754

@@ -92,19 +89,19 @@ directly.
9289
But that's an implementation detail specific to the Retrofit library.
9390
With other libraries, the API will be different, but the concept is the same:
9491

95-
_Our code with `suspend` functions looks surprisingly similar to the "blocking" version.
96-
It's readable and expresses exactly what we're trying to achieve._
92+
Our code with `suspend` functions looks surprisingly similar to the "blocking" version.
93+
It's readable and expresses exactly what we're trying to achieve.
9794

9895
The major difference with a blocking version is that instead of blocking the thread, we suspend the coroutine:
9996

10097
```
101-
thread -> coroutine
10298
block -> suspend
99+
thread -> coroutine
103100
```
104101

105102
Coroutines are often called light-weight threads.
106103
That means we can run code on coroutines similar to how we run code on threads.
107-
However, the operations that were blocking before (and had to be avoided because of that),
104+
The operations that were blocking before (and had to be avoided because of that),
108105
can now suspend the coroutine instead.
109106

110107
How can we start a new coroutine?
@@ -129,7 +126,7 @@ so, we'll simply say that in this case, `launch` _starts a new coroutine_ that i
129126
for loading data and showing the results.
130127

131128
Coroutines are computations that run on top of threads and can be suspended.
132-
By saying "suspended", we mean that the corresponding computation can be paused,
129+
When a coroutine is "suspended", the corresponding computation is paused,
133130
removed from the thread, and stored in memory.
134131
Meanwhile, the thread is free to be occupied with other activities:
135132

@@ -170,7 +167,7 @@ We can also modify the template for running all the Kotlin files and enable this
170167
In our case, all the code runs on one coroutine,
171168
the mentioned above "load contributors" coroutine, denoted as `@coroutine#1`.
172169

173-
However, in this version, while waiting for the result, we don't reuse the thread for sending other requests,
170+
In this version, while waiting for the result, we don't reuse the thread for sending other requests,
174171
because we have written our code in a sequential way. The new request is sent only when the previous result is received.
175172
`suspend` functions treat the thread fairly and don't block it for "waiting",
176173
but it doesn't yet bring any concurrency to the picture. Let's see how this can be improved.

Introduction to Coroutines and Channels/05_Concurrency.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
Kotlin coroutines are extremely inexpensive in comparison to threads.
44
Each time when we want to start a new computation asynchronously, we can create a new coroutine.
55

6-
To start a new coroutine we can just use one of the main "coroutine builders": `launch`, `async`, or `runBlocking`.
6+
To start a new coroutine we use one of the main "coroutine builders": `launch`, `async`, or `runBlocking`.
77
Different libraries can define additional coroutine builders.
88

99
`async` starts a new coroutine and returns a `Deferred` object.

Introduction to Coroutines and Channels/06_StructuredConcurrency.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
_Coroutine scope_ is responsible for the structure and parent-child relationships between different coroutines.
44
We always start new coroutines inside a scope.
55
_Coroutine context_ stores additional technical information used to run a given coroutine,
6-
like the dispatcher specifying the thread or threads the coroutine should be scheduled on.
6+
like the coroutine custom name, or the dispatcher specifying the threads the coroutine should be scheduled on.
77

88
When `launch`, `async`, or `runBlocking` are used to start a new coroutine, they automatically create the corresponding scope.
99
All these functions take a lambda with receiver as an argument, and the implicit receiver type is the `CoroutineScope`:

Introduction to Coroutines and Channels/07_Progress.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Despite the information for some repositories being loaded rather fast,
44
the user only sees the resulting list once all the data is loaded.
55
Until then, the loader icon runs showing the progress, but there's no information about the current state,
66
and what contributors are already loaded.
7-
However, we could show the intermediate results earlier and display all the contributors after loading the data
7+
We could show the intermediate results earlier and display all the contributors after loading the data
88
for each of the repositories:
99

1010
![](./assets/7-progress/Loading.gif)
@@ -35,10 +35,10 @@ launch(Dispatchers.Default) {
3535
}
3636
```
3737

38-
Note that the `updateResults` parameter is declared as `suspend` in `loadContributorsProgress`.
38+
The `updateResults` parameter is declared as `suspend` in `loadContributorsProgress`.
3939
We need that to call `withContext`, which is a `suspend` function inside the corresponding lambda argument.
4040

41-
Note also that `updateResults` callback now takes an additional `Boolean` parameter as an argument saying whether
41+
`updateResults` callback takes an additional `Boolean` parameter as an argument saying whether
4242
all the loading completed and our results are final.
4343

4444
#### Task
@@ -86,7 +86,7 @@ An `updateResults` callback is called after each request is completed:
8686

8787
We haven't used any concurrency so far. This code is sequential, so we don't need synchronization.
8888

89-
However, we'd like to send requests concurrently and update the intermediate results after getting the response
89+
We'd like to send requests concurrently and update the intermediate results after getting the response
9090
for each repository:
9191

9292
![](./assets/7-progress/ProgressAndConcurrency.png)

Introduction to Coroutines and Channels/08_Channels.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ Since we call the `receive` calls sequentially, no additional synchronization is
176176
As with the `loadContributorsProgress` function, we can create an `allUsers` variable to store
177177
the intermediate states of the "all contributors" list.
178178
When we receive each new list from the channel,
179-
we can add it to the list of all users, aggregate the result, and update the state using the `updateResults` callback:
179+
we add it to the list of all users, aggregate the result, and update the state using the `updateResults` callback:
180180

181181
```kotlin
182182
suspend fun loadContributorsChannels(
@@ -218,6 +218,6 @@ We've learned how to use suspend functions, execute coroutines concurrently, and
218218
information between coroutines using channels.
219219

220220
Note that neither coroutines nor channels will completely eradicate the complexity that comes from concurrency,
221-
but they will definitely make your life easier when we need to reason it and understand what's going on.
221+
but they will definitely make your life easier when you need to reason it and understand what's going on.
222222

223223
Next, we'll discuss how to test the code that uses coroutines.

Introduction to Coroutines and Channels/09_Testing.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Testing coroutines
22

33
Let's discuss how to test the code that uses coroutines.
4-
It'd be nice to test our solutions and make sure that the solution with concurrent coroutines is faster than the solution
4+
It'd be nice to test our solutions, make sure that the solution with concurrent coroutines is faster than the solution
55
with `suspend` functions, and check that the solution with channels is faster than the simple "progress" one.
66
Let's have a look at how to compare the total running time of these solutions.
77

@@ -90,7 +90,7 @@ while virtual time equals the delay argument exactly, which is 1000 milliseconds
9090
To enjoy the full effect of "virtual" `delay` in child coroutines,
9191
we should start all the child coroutines with `TestCoroutineDispatcher`.
9292
Otherwise, it won't work.
93-
This dispatcher is automatically inherited from the other `TestCoroutineScope`, unless we provide the same dispatchers:
93+
This dispatcher is automatically inherited from the other `TestCoroutineScope`, unless we provide a different dispatcher:
9494

9595
```kotlin
9696
@Test
@@ -123,7 +123,7 @@ which is more flexible and easier to test.
123123
Note that the testing API that supports virtual time is experimental and may change in the future.
124124
By default, we'll see compiler warnings if we use it.
125125
To suppress these warnings, we need to annotate the test function or the whole class containing the tests.
126-
We can add `@UseExperimental(ExperimentalCoroutinesApi::class)` to our test class or function.
126+
We can add `@OptIn(ExperimentalCoroutinesApi::class)` to our test class or function.
127127
By adding such annotation, we emphasize that we understand that the API can change and is ready
128128
to update our usages if needed (most probably, automatically).
129129

@@ -211,7 +211,7 @@ The first intermediate result for the last version with 'channels' is available
211211
and we can see that difference in tests using virtual time.
212212

213213
The tests for the remaining "suspend" and "progress" tasks are very similar;
214-
we can find them in the project 'solutions' branch.
214+
you can find them in the project 'solutions' branch.
215215

216216
You can find more information about using virtual time and
217217
experimental testing package [here](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-test/).

0 commit comments

Comments
 (0)