티스토리 뷰

Android/Kotlin

[Kotlin]  Coroutine (2)

혀가 길지 않은 개발자 2020. 7. 29. 12:01

build.gradle (Module: app)

dependencies {
    // Coroutine
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.7'
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.4'
}

 

 

 

 

 

 

 

MainActivity.kt

package com.jwsoft.kotlinproject

import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import kotlinx.coroutines.*

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        GlobalScope.launch {

            val valueOne: Int = async {
                1 + 1
            }.await()

            Log.e("valueOne : ", "$valueOne")

            val valueTwo: Int = withContext(Dispatchers.Default) {
                2 + 2
            }

            Log.e("valueTwo", "$valueTwo")

            val valueThree: Int = async {
                3 + 3
            }.await()

            Log.e("valueThree : ", "$valueThree")

        }
    }

}

실행 결과

 

 

 

 

 

 


MainActivity.kt

package com.jwsoft.kotlinproject

import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import kotlinx.coroutines.*

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        GlobalScope.launch {
            checkAfter2Sec()
            Log.e("", "이미지 받아오는 작업")
        }

    }

    private suspend fun checkAfter2Sec() {
        GlobalScope.launch {
            delay(2000)
            Log.e("", "2초 후 작업 완료 여부 확인")
        }
    }

}

실행 결과

 

 

 

 

 

 

MainActivity.kt

package com.jwsoft.kotlinproject

import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import kotlinx.coroutines.*

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        GlobalScope.launch {
            checkAfter2Sec()
            Log.e("", "이미지 받아오는 작업")
        }

    }

    private suspend fun checkAfter2Sec() {
        runBlocking {
            delay(2000)
            Log.e("", "2초 후 작업 완료 여부 확인")
        }
    }

}

GlobalScope.launch 에서 runBlocking 으로 수정

 

실행 결과

 

 

 

 

 

 


MainActivity.kt

package com.jwsoft.kotlinproject

import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import kotlinx.coroutines.*

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        GlobalScope.launch(Dispatchers.Main) {

            val routineIO = async(Dispatchers.IO) {
                "DB에서 사용자 정보 가져오기"
            }.await()

            Log.e("IO 작업", routineIO)

            val routineDefault = async(Dispatchers.Default) {
                "사용자 정보를 이용하여 백그라운드 작업"
            }.await()

            Log.e("Default 작업", routineDefault)
            Log.e("Main 작업", "작업을 거친 정보 UI에 노출")
        }
    }

}

실행 결과

 

 

 

 

 

MainActivity.kt

package com.jwsoft.kotlinproject

import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import kotlinx.coroutines.*

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        GlobalScope.launch(Dispatchers.Main) {

            val routineIO = withContext(Dispatchers.IO) {
                "DB에서 사용자 정보 가져오기"
            }
            Log.e("IO 작업", routineIO)

            val routineDefault = withContext(Dispatchers.Default) {
                "사용자 정보를 이용하여 백그라운드 작업"
            }
            Log.e("Default 작업", routineDefault)

            Log.e("Main 작업", "작업을 거친 정보 UI에 노출")
        }
    }

}

실행 결과

 

 

 

 

 

 

 


activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

   <Button
       android:id="@+id/btnMain"
       android:layout_width="match_parent"
       android:layout_height="90dp"
       android:textAllCaps="false"
       android:text="Main"
       android:textSize="24dp"
       app:layout_constraintTop_toTopOf="parent"
       app:layout_constraintBottom_toBottomOf="parent"
       app:layout_constraintLeft_toLeftOf="parent"
       app:layout_constraintRight_toRightOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

activity_main.xml

 

 

 

 

 

activity_sub.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/btnSub"
        android:layout_width="match_parent"
        android:layout_height="90dp"
        android:textAllCaps="false"
        android:text="Sub"
        android:textSize="24dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

activity_sub.xml

 

 

 

 

SubActivity.kt

package com.jwsoft.kotlinproject

import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_sub.*

class SubActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_sub)

        btnSub.setOnClickListener {
            startActivity(Intent(applicationContext, MainActivity::class.java))
        }

    }
}

 

 

 

 

 

 

 

 

MainActivity.kt

package com.jwsoft.kotlinproject

import android.content.Intent
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.coroutines.*

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        GlobalScope.launch(Dispatchers.Main) {
            repeat(100) {
                Toast.makeText(applicationContext, "${it+1} 번 째 메인 토스트 메시지", Toast.LENGTH_SHORT).show()
                delay(4000)
            }
        }

        btnMain.setOnClickListener {
            startActivity(Intent(applicationContext, SubActivity::class.java))
            finish()
        }
    }

}

실행 결과

액티비티 이동해도 토스트 메시지는 살아있음.
이로 인해 메인 액티비티로 여러 번 이동 시 여러 개의 루틴이 생성됨.
앱을 종료해도 쌓여있는 루틴이 계속 나옴.

 

 

 

 

 

 

 

 

MainActivity.kt

package com.jwsoft.kotlinproject

import android.content.Intent
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.coroutines.*

class MainActivity : AppCompatActivity() {

    private lateinit var job: Job

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        job = GlobalScope.launch(Dispatchers.Main) {
            repeat(100) {
                Toast.makeText(applicationContext, "${it+1} 번 째 메인 토스트 메시지", Toast.LENGTH_SHORT).show()
                delay(4000)
            }
        }

        btnMain.setOnClickListener {
            startActivity(Intent(applicationContext, SubActivity::class.java))
            finish()
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        job.cancel()
    }

}

Job으로 GlobalScope를 제어한다.

액티비티 이동 시 해당 코루틴이 취소되므로 이전 문제가 해결됨

 

실행 결과

 

 

 

 

 

MainActivity.kt

package com.jwsoft.kotlinproject

import android.content.Intent
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.coroutines.*
import kotlin.coroutines.CoroutineContext

class MainActivity : AppCompatActivity(), CoroutineScope {

    private var job: Job = Job()

    override val coroutineContext: CoroutineContext
        get() = Dispatchers.Main + job

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        launch(Dispatchers.Main) {
            repeat(100) {
                Toast.makeText(applicationContext, "${it+1} 번 째 메인 토스트 메시지", Toast.LENGTH_SHORT).show()
                delay(4000)
            }
        }

        btnMain.setOnClickListener {
            startActivity(Intent(applicationContext, SubActivity::class.java))
            finish()
        }
    }

}

실행 결과

액티비티 이동해도 토스트 메시지는 살아있음.
이로 인해 메인 액티비티로 여러 번 이동 시 여러 개의 루틴이 생성됨.
앱을 종료해도 쌓여있는 루틴이 계속 나옴.

 

 

 

 

 

 

 

 

MainActivity.kt

package com.jwsoft.kotlinproject

import android.content.Intent
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.coroutines.*
import kotlin.coroutines.CoroutineContext

class MainActivity : AppCompatActivity(), CoroutineScope {

    private var job: Job = Job()

    override val coroutineContext: CoroutineContext
        get() = Dispatchers.Main + job

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        launch(Dispatchers.Main) {
            repeat(100) {
                Toast.makeText(applicationContext, "${it+1} 번 째 메인 토스트 메시지", Toast.LENGTH_SHORT).show()
                delay(4000)
            }
        }

        btnMain.setOnClickListener {
            startActivity(Intent(applicationContext, SubActivity::class.java))
            finish()
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        job.cancel()
    }

}

job.cancel() 추가.

액티비티 이동 시 해당 코루틴이 취소되므로 이전 문제가 해결됨

 

실행 결과

 

 

 

 

참고

codechacha.com/ko/android-coroutine/

 

안드로이드 - Kotlin Coroutine을 사용하는 방법

Kotlin Coroutine은 가벼운 쓰레드(Light-weight thread)입니다. 비동기적인(asynchronous) 프로그래밍이 가능하게 만들어 줍니다. async, launch, coroutine context 등의 코루틴 키워드를 설명하고 어떻게 코루틴을 작

codechacha.com

 

 

 

 

'Android > Kotlin' 카테고리의 다른 글

[Kotlin]  Coroutine  +  CoroutineExceptionHandler  (0) 2020.07.29
[Kotlin]  Coroutine  +  ViewModel  (0) 2020.07.29
[Kotlin]  Thread.join()  (0) 2020.07.27
[Kotlin]  Synchronized  (0) 2020.07.27
[Kotlin]  Generics  (0) 2020.07.27
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함