Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit fe901e6

Browse files
Merge pull request #4 from oiyio/master
added sequence, channels, flow samples
2 parents f177ecd + bad6b20 commit fe901e6

File tree

57 files changed

+827
-153
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+827
-153
lines changed

‎Tutorial1-1CoroutinesBasics/build.gradle‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,4 +161,5 @@ dependencies {
161161
// Espresso
162162
androidTestImplementation "androidx.test.espresso:espresso-contrib:$espressoVersion"
163163

164+
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.2.0"
164165
}

‎Tutorial1-1CoroutinesBasics/src/main/AndroidManifest.xml‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
33
package="com.smarttoolfactory.tutorial1_1basics">
44

5-
<uses-permission android:name="android.permission.INTERNET"/>
5+
<uses-permission android:name="android.permission.INTERNET"/>
66

77
<application
88
android:allowBackup="true"
@@ -22,6 +22,7 @@
2222
<activity android:name="com.smarttoolfactory.tutorial1_1coroutinesbasics.chapter1_basics.Activity1Basics" />
2323
<activity android:name="com.smarttoolfactory.tutorial1_1coroutinesbasics.chapter2_scopes.Activity2CoroutineScope"/>
2424
<activity android:name="com.smarttoolfactory.tutorial1_1coroutinesbasics.chapter3_lifecycle.Activity3CoroutineLifecycle" />
25+
<activity android:name="com.smarttoolfactory.tutorial1_1coroutinesbasics.chapter3_lifecycle.Activity3LifecycleScope" />
2526
<activity android:name="com.smarttoolfactory.tutorial1_1coroutinesbasics.chapter4_supervisorjob.Activity4SupervisorJob" />
2627
<activity android:name="com.smarttoolfactory.tutorial1_1coroutinesbasics.chapter5_viewmodel.Activity5ViewModelScope" />
2728
<activity android:name="com.smarttoolfactory.tutorial1_1coroutinesbasics.chapter5_viewmodel.Activity5ViewModelRxJava" />

‎Tutorial1-1CoroutinesBasics/src/main/java/com/smarttoolfactory/tutorial1_1coroutinesbasics/MainActivity.kt‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import com.smarttoolfactory.tutorial1_1coroutinesbasics.adapter.ChapterSelection
1414
import com.smarttoolfactory.tutorial1_1coroutinesbasics.chapter1_basics.Activity1Basics
1515
import com.smarttoolfactory.tutorial1_1coroutinesbasics.chapter2_scopes.Activity2CoroutineScope
1616
import com.smarttoolfactory.tutorial1_1coroutinesbasics.chapter3_lifecycle.Activity3CoroutineLifecycle
17+
import com.smarttoolfactory.tutorial1_1coroutinesbasics.chapter3_lifecycle.Activity3LifecycleScope
1718
import com.smarttoolfactory.tutorial1_1coroutinesbasics.chapter4_supervisorjob.Activity4SupervisorJob
1819
import com.smarttoolfactory.tutorial1_1coroutinesbasics.chapter5_viewmodel.Activity5ViewModelRxJava
1920
import com.smarttoolfactory.tutorial1_1coroutinesbasics.chapter5_viewmodel.Activity5ViewModelScope
@@ -42,6 +43,7 @@ class MainActivity : AppCompatActivity(), BaseAdapter.OnRecyclerViewItemClickLis
4243
activityClassModels.add(ActivityClassModel(Activity1Basics::class.java))
4344
activityClassModels.add(ActivityClassModel(Activity2CoroutineScope::class.java))
4445
activityClassModels.add(ActivityClassModel(Activity3CoroutineLifecycle::class.java))
46+
activityClassModels.add(ActivityClassModel(Activity3LifecycleScope::class.java))
4547
activityClassModels.add(ActivityClassModel(Activity4SupervisorJob::class.java))
4648
activityClassModels.add(ActivityClassModel(Activity5ViewModelScope::class.java))
4749
activityClassModels.add(ActivityClassModel(Activity5ViewModelRxJava::class.java))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package com.smarttoolfactory.tutorial1_1coroutinesbasics.chapter3_lifecycle
2+
3+
import android.os.Bundle
4+
import android.widget.Toast
5+
import androidx.appcompat.app.AlertDialog
6+
import androidx.appcompat.app.AppCompatActivity
7+
import androidx.lifecycle.lifecycleScope
8+
import com.smarttoolfactory.tutorial1_1basics.R
9+
import com.smarttoolfactory.tutorial1_1basics.databinding.Activity3LifecycleScopeBinding
10+
import com.smarttoolfactory.tutorial1_1coroutinesbasics.util.dataBinding
11+
import kotlinx.coroutines.delay
12+
import kotlinx.coroutines.launch
13+
14+
/*
15+
lifecycleScope.launch{} is an alternatie to Handler().postDelayed()
16+
17+
activity.lifecycleScope.launch {
18+
// scope bound to Activity Lifecycle
19+
}
20+
fragment.lifecycleScope.launch {
21+
// scope bound to Fragment Lifecycle
22+
}
23+
fragment.viewLifecycleOwner.launch{
24+
// scope bound to Fragment View
25+
}
26+
27+
Be aware that lifecycleScope is convenient when dealing with UI events like, for example, showing a tip for the user and hiding it after a small delay.
28+
lifecycleScope.launch {
29+
delay(5000)
30+
showTip()
31+
delay(5000)
32+
hideTip()
33+
}
34+
35+
Without using Coroutines and lifecycleScope, this would be:
36+
val DELAY = 5000
37+
Handler().postDelayed({
38+
showTip()
39+
Handler().postDelayed({
40+
hideTip()
41+
}, DELAY)
42+
}, DELAY)
43+
44+
LifecycleScope is bound to Dispatcher.Main. That means if you don’t change Dispatcher explicitly all the coroutines inside LifecycleScope will be executed on the main thread.
45+
46+
https://medium.com/corouteam/exploring-kotlin-coroutines-and-lifecycle-architectural-components-integration-on-android-c63bb8a9156f
47+
https://android.jlelse.eu/coroutine-in-android-working-with-lifecycle-fc9c1a31e5f3
48+
https://kotlin.christmas/2019/13
49+
* */
50+
51+
class Activity3LifecycleScope : AppCompatActivity(R.layout.activity3_lifecycle_scope) {
52+
53+
private val binding: Activity3LifecycleScopeBinding by dataBinding()
54+
55+
override fun onCreate(savedInstanceState: Bundle?) {
56+
super.onCreate(savedInstanceState)
57+
58+
val builder = AlertDialog.Builder(this)
59+
builder.setMessage("Mesajj")
60+
builder.setTitle("Titlee")
61+
val alertDialog = builder.create()
62+
63+
64+
binding.button1.setOnClickListener {
65+
binding.textViewResult.text = binding.textViewResult.text.toString() + "Clicked\n"
66+
lifecycleScope.launch {
67+
68+
binding.textViewResult.text =
69+
binding.textViewResult.text.toString() + "🤓 Delay 5 sn before showing dialog\n"
70+
delay(5000)
71+
72+
alertDialog.show()
73+
74+
binding.textViewResult.text =
75+
binding.textViewResult.text.toString() + "🥳 Delay 5 sn after showing dialog\n"
76+
delay(5000)
77+
78+
binding.textViewResult.text =
79+
binding.textViewResult.text.toString() + "Dismissed AlertDialog \n"
80+
Toast.makeText(baseContext, "Dismissed AlertDialog", Toast.LENGTH_SHORT).show()
81+
alertDialog.dismiss()
82+
}
83+
binding.textViewResult.text =
84+
binding.textViewResult.text.toString() + "🚗🚗🚗 Codes after lifecycleScope \n"
85+
}
86+
87+
}
88+
}

‎Tutorial1-1CoroutinesBasics/src/main/java/com/smarttoolfactory/tutorial1_1coroutinesbasics/chapter5_viewmodel/CoroutinesViewModel.kt‎

Lines changed: 42 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -44,24 +44,24 @@ class CoroutinesViewModel(private val viewModelDispatcher: CoroutineDispatcher)
4444

4545
fun getMockResult(timeMillis: Long = 2000) {
4646

47-
println("getMockResult() loading...")
47+
println("1 - getMockResult() loading...")
4848
result.value = "Loading..."
4949
enableResultButton.value = false
5050

5151
viewModelScope.launch {
5252

53-
println("🙄 getMockResult() START ViewModel scope: $this, thread: ${Thread.currentThread().name}")
53+
println("🙄 2 - getMockResult() START ViewModel scope: $this, thread: ${Thread.currentThread().name}")
5454

55-
result.value = generateMockNetworkResponseOrThrowException(timeMillis)
55+
result.value = generateMockNetworkResponseOrThrowException(timeMillis)// 4
5656
enableResultButton.value = true
5757

58-
println("getMockResult() ViewModel scope AFTER generateMockNetworkResponse() ${result.value}")
58+
println("5 - getMockResult() ViewModel scope AFTER generateMockNetworkResponse() ${result.value}")
5959

6060
}
6161

62-
println("getMockResult() END OF FUN")
62+
println("3 - getMockResult() END OF FUN")
6363

64-
/*
64+
/* 1 2 4 3 5
6565
Prints:
6666
I: getMockResult() loading...
6767
I: 🙄 getMockResult() ViewModel scope: StandaloneCoroutine{Active}@ef7c60d, thread: main
@@ -72,55 +72,45 @@ class CoroutinesViewModel(private val viewModelDispatcher: CoroutineDispatcher)
7272

7373
}
7474

75-
76-
/**
77-
* This method is for Unit-Testing exceptions
75+
/*
76+
Mock Response Functions
7877
*/
79-
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
80-
fun throwExceptionInAScope(coroutineContext: CoroutineContext) {
81-
82-
println("getMockResult() loading...")
8378

84-
// 🔥🔥
85-
viewModelScope.launch(coroutineContext) {
86-
87-
println("🙄 getMockResult() START ViewModel scope: $this, thread: ${Thread.currentThread().name}")
88-
89-
delay(2000)
90-
throw RuntimeException("Exception Occurred")
79+
private suspend fun generateMockNetworkResponseOrThrowException(timeMillis: Long = 2000): String {
9180

92-
}
81+
println("🥶 4 - generateMockNetworkResponse() thread: ${Thread.currentThread().name}")
9382

94-
println("getMockResult() END OF FUN")
83+
delay(timeMillis)
9584

85+
if (timeMillis > 2000) throw RuntimeException("Threw Network Exception")
9686

87+
return "Hello World"
9788
}
9889

99-
10090
fun getMockResultFromDispatcherThread(timeMillis: Long) {
10191

102-
println("getMockResult() loading...")
92+
println("1 - getMockResult() loading...")
10393
result.value = "Loading..."
10494
enableResultButton.value = false
10595

10696
viewModelScope.launch(Dispatchers.Default) {
10797

108-
println("🙄 getMockResult() ViewModel scope: $this, thread: ${Thread.currentThread().name}")
98+
println("🙄 3 - getMockResult() ViewModel scope: $this, thread: ${Thread.currentThread().name}")
10999

110100
withContext(Dispatchers.Main) {
111-
result.value = generateMockNetworkResponseOrThrowException(timeMillis)
101+
result.value = generateMockNetworkResponseOrThrowException(timeMillis)// 4
112102
enableResultButton.value = true
113103

114104
}
115105

116-
println("getMockResult() ViewModel scope AFTER")
106+
println("5 - getMockResult() ViewModel scope AFTER")
117107

118108
}
119109

120-
println("getMockResult() END OF FUN")
110+
println("2 - getMockResult() END OF FUN")
121111

122112
/*
123-
Prints:
113+
Prints: 1 3 2 4 5 or 1 2 3 4 5
124114
125115
*/
126116

@@ -155,9 +145,9 @@ class CoroutinesViewModel(private val viewModelDispatcher: CoroutineDispatcher)
155145
// longer than 2000 ms
156146
resultWithTimeout.value = generateMockNetworkResponseOrThrowException()
157147
} catch (exception: TimeoutCancellationException) {
158-
resultWithTimeout.value = exception.message
148+
resultWithTimeout.value = "1 - "+exception.message
159149
} catch (exception: Exception) {
160-
resultWithTimeout.value = exception.message
150+
resultWithTimeout.value = "2 - "+exception.message
161151
}
162152

163153
}
@@ -283,21 +273,6 @@ class CoroutinesViewModel(private val viewModelDispatcher: CoroutineDispatcher)
283273

284274
}
285275

286-
/*
287-
Mock Response Functions
288-
*/
289-
290-
private suspend fun generateMockNetworkResponseOrThrowException(timeMillis: Long = 2000): String {
291-
292-
println("🥶 generateMockNetworkResponse() thread: ${Thread.currentThread().name}")
293-
294-
delay(timeMillis)
295-
296-
if (timeMillis > 2000) throw RuntimeException("Threw Network Exception")
297-
298-
return "Hello World"
299-
}
300-
301276
private suspend fun generateRandomCity(): String {
302277
val cityList = listOf("Berlin", "New York", "London", "Paris", "Istanbul")
303278

@@ -317,6 +292,27 @@ class CoroutinesViewModel(private val viewModelDispatcher: CoroutineDispatcher)
317292

318293
}
319294

295+
/**
296+
* This method is for Unit-Testing exceptions
297+
*/
298+
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
299+
fun throwExceptionInAScope(coroutineContext: CoroutineContext) {
300+
301+
println("getMockResult() loading...")
302+
303+
// 🔥🔥
304+
viewModelScope.launch(coroutineContext) {
305+
306+
println("🙄 getMockResult() START ViewModel scope: $this, thread: ${Thread.currentThread().name}")
307+
308+
delay(2000)
309+
throw RuntimeException("Exception Occurred")
310+
311+
}
312+
313+
println("getMockResult() END OF FUN")
314+
315+
}
320316
}
321317

322318
class CoroutinesViewModelFactory :
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
// This file was automatically generated from channels.md by Knit tool. Do not edit.
6+
package com.smarttoolfactory.tutorial1_1coroutinesbasics.playground
7+
8+
import kotlinx.coroutines.channels.Channel
9+
import kotlinx.coroutines.launch
10+
import kotlinx.coroutines.runBlocking
11+
12+
/*
13+
Rendezvous channel example
14+
*/
15+
16+
17+
fun main() = runBlocking {
18+
val channel = Channel<String>()
19+
20+
launch {
21+
println("Sending A1")
22+
channel.send("A1")
23+
println("Sending A2")
24+
channel.send("A2")
25+
println("A done")
26+
}
27+
28+
launch {
29+
println("Sending B1")
30+
channel.send("B1")
31+
println("B done")
32+
}
33+
34+
launch {
35+
repeat(3) {
36+
println("Calling receive()")
37+
val x = channel.receive()
38+
println("receive is done $x")
39+
}
40+
}
41+
42+
println("Done!")
43+
}
44+
45+
/*
46+
* Output :
47+
48+
Done!
49+
Sending A1
50+
Sending B1
51+
Calling receive()
52+
receive is done A1
53+
Calling receive()
54+
receive is done B1
55+
Calling receive()
56+
Sending A2
57+
A done
58+
B done
59+
receive is done A2
60+
61+
* */
Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,26 @@
66
package com.smarttoolfactory.tutorial1_1coroutinesbasics.playground
77

88
import kotlinx.coroutines.channels.Channel
9+
import kotlinx.coroutines.delay
910
import kotlinx.coroutines.launch
1011
import kotlinx.coroutines.runBlocking
1112

12-
fun main() = runBlocking {
13+
fun main() = runBlocking { // coroutine 1
14+
1315
val channel = Channel<Int>()
14-
launch {
16+
launch {// coroutine 2
1517
// this might be heavy CPU-consuming computation or async logic, we'll just send five squares
16-
for (x in 1..5) channel.send(x * x)
18+
for (x in 1..5) {
19+
println("send $x ")
20+
channel.send(x * x)
21+
}
22+
1723
}
1824
// here we print five received integers:
19-
repeat(5) { println(channel.receive()) }
25+
repeat(5) {
26+
delay(3000)
27+
println(channel.receive())
28+
}
2029
println("Done!")
2130
}
31+

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /