diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
index 1bec35e..fe581ad 100644
--- a/.idea/codeStyles/Project.xml
+++ b/.idea/codeStyles/Project.xml
@@ -1,8 +1,165 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ xmlns:android
+
+ ^$
+
+
+
+
+
+
+
+
+ xmlns:.*
+
+ ^$
+
+
+ BY_NAME
+
+
+
+
+
+
+ .*:id
+
+ http://schemas.android.com/apk/res/android
+
+
+
+
+
+
+
+
+ .*:name
+
+ http://schemas.android.com/apk/res/android
+
+
+
+
+
+
+
+
+ name
+
+ ^$
+
+
+
+
+
+
+
+
+ style
+
+ ^$
+
+
+
+
+
+
+
+
+ .*
+
+ ^$
+
+
+ BY_NAME
+
+
+
+
+
+
+ .*
+
+ http://schemas.android.com/apk/res/android
+
+
+ ANDROID_ATTRIBUTE_ORDER
+
+
+
+
+
+
+ .*
+
+ .*
+
+
+ BY_NAME
+
+
+
+
+
diff --git a/.idea/dbnavigator.xml b/.idea/dbnavigator.xml
new file mode 100644
index 0000000..02612e8
--- /dev/null
+++ b/.idea/dbnavigator.xml
@@ -0,0 +1,456 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 703e5d4..af0bbdd 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -5,7 +5,7 @@
-
+
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/codingwithmitch/coroutineexamples/MainActivity.kt b/app/src/main/java/com/codingwithmitch/coroutineexamples/MainActivity.kt
index ac6828a..f4879b3 100644
--- a/app/src/main/java/com/codingwithmitch/coroutineexamples/MainActivity.kt
+++ b/app/src/main/java/com/codingwithmitch/coroutineexamples/MainActivity.kt
@@ -2,6 +2,9 @@ package com.codingwithmitch.coroutineexamples
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
+import android.util.Log
+import android.widget.ProgressBar
+import android.widget.Toast
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.coroutines.*
import kotlinx.coroutines.Dispatchers.IO
@@ -10,65 +13,125 @@ import kotlinx.coroutines.Dispatchers.Main
class MainActivity : AppCompatActivity() {
+ private val TAG: String = "AppDebug"
+
+ private val PROGRESS_MAX = 2500000
+ private val PROGRESS_START = 0
+ private val JOB_TIME = 4000 // ms
+ private lateinit var job: CompletableJob
+
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
- button.setOnClickListener {
- setNewText("Click!")
+ job_button.setOnClickListener {
+ if(!::job.isInitialized){
+ initjob()
+ }
+ job_progress_bar.startJobOrCancel()
+ }
+ }
- CoroutineScope(IO).launch {
- fakeApiRequest()
+ fun resetjob(){
+ if(job.isActive || job.isCompleted){
+ job.cancel(CancellationException("Resetting job"))
+ job.complete()
+ }
+ initjob()
+ }
+
+ fun initjob(){
+ job_button.setText("Start Job #1")
+ updateJobCompleteTextView("")
+ job = Job()
+ job.invokeOnCompletion {
+ it?.message.let{
+ var msg = it
+ if(msg.isNullOrBlank()){
+ msg = "Unknown cancellation error."
+ }
+ Log.e(TAG, "${job} was cancelled. Reason: ${msg}")
+ showToast(msg)
}
}
-
+ job_progress_bar.max = PROGRESS_MAX
+ job_progress_bar.progress = PROGRESS_START
}
- private fun setNewText(input: String){
- val newText = text.text.toString() + "\n$input"
- text.text = newText
+
+ fun ProgressBar.startJobOrCancel(){
+ if(this.progress > 0){
+ Log.d(TAG, "${job} is already active. Cancelling...")
+ resetjob()
+ }
+ else{
+ this.progress = 0
+ job_button.setText("Cancel Job #1")
+ CoroutineScope(IO + job).launch{
+ Log.d(TAG, "coroutine ${this} is activated with job ${job}.")
+
+ for(i in PROGRESS_START..PROGRESS_MAX){
+ //delay((JOB_TIME / PROGRESS_MAX).toLong())
+ if (i % 25000 == 0) Log.d("From_me", "for(i in PROGRESS_START..PROGRESS_MAX: $i")
+ this@startJobOrCancel.progress = i
+ }
+ updateJobCompleteTextView("Job is complete!")
+ }.let {
+ it.invokeOnCompletion {
+ job.complete()
+ }
+ }
+ }
}
- private suspend fun setTextOnMainThread(input: String) {
- withContext (Main) {
- setNewText(input)
+
+ private fun updateJobCompleteTextView(text: String){
+ GlobalScope.launch (Main){
+ job_complete_text.setText(text)
}
}
- private suspend fun fakeApiRequest() {
- coroutineScope {
+ private fun showToast(text: String){
+ GlobalScope.launch (Main){
+ Toast.makeText(this@MainActivity, text, Toast.LENGTH_SHORT).show()
+ }
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ job.cancel()
+ }
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
- launch {
- val result1 = getResult1FromApi() // wait until job is done
- if ( result1.equals("Result #1")) {
- setTextOnMainThread("Got $result1")
- val result2 = getResult2FromApi() // wait until job is done
- if (result2.equals("Result #2")) {
- setTextOnMainThread("Got $result2")
- } else {
- setTextOnMainThread("Couldn't get Result #2")
- }
- } else {
- setTextOnMainThread("Couldn't get Result #1")
- }
- }
- }
- }
- private suspend fun getResult1FromApi(): String {
- delay(1000) // Does not block thread. Just suspends the coroutine inside the thread
- return "Result #1"
- }
- private suspend fun getResult2FromApi(): String {
- delay(1000)
- return "Result #2"
- }
-}
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 6fa9380..55f1e11 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -5,28 +5,49 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
- tools:context=".MainActivity">
+ tools:context=".MainActivity"
+ android:padding="10dp">
-
+ android:layout_marginTop="50dp"
+ android:id="@+id/layout1"
+ android:orientation="vertical"
+ android:gravity="center"
+ app:layout_constraintVertical_chainStyle="packed"
+ >
+
+
+
+
+
+
+
+
+
+
-
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index b3afd85..4420c59 100644
--- a/build.gradle
+++ b/build.gradle
@@ -8,7 +8,7 @@ buildscript {
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.4.0'
+ classpath 'com.android.tools.build:gradle:3.5.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index f6ae38c..db55e59 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Thu Jul 25 09:13:06 PDT 2019
+#Thu Aug 29 13:47:07 CEST 2019
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip