๋ณธ ๊ฒ์๊ธ์ Coroutine ๊ฐ๋ ์ Android ๋ด์์ ์ฌ์ฉ๋๋ ๊ฒ์ ์ ์ ๋ก ์์ฑ๋์๋ค.
#1 ์ด์ ๊ฒ์๊ธ
[Kotlin] Coroutines - ViewModelScope
๋ณธ ๊ฒ์๊ธ์ Coroutine ๊ฐ๋ ์ Android ๋ด์์ ์ฌ์ฉ๋๋ ๊ฒ์ ์ ์ ๋ก ์์ฑ๋์๋ค. #1 ViewModel ์ ์ ํต์ ์ธ ๋ฐฉ์์ Coroutinesimport androidx.lifecycle.ViewModel import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.D
kenel.tistory.com
์ด์ ๊ฒ์๊ธ์์ ViewModel์ ์๋ช ์ฃผ๊ธฐ๋ฅผ ์ฐธ์กฐํด, ViewModel์ด ์๋ฉธ๋ ๋ ์์์ ์ข ๋ฃ๋๋ CoroutineScope์ ๋ํด ๋ค๋ค๋ค. ์ด๋ฒ์ ๊ทธ ์ฐธ์กฐ์ ๋์์ด LifecycleOwner์ธ ๋ฒ์ ์ ์ดํด๋ณธ๋ค. ์ด์ ๊ธ๊ณผ ๊ฑฐ์ ๋น์ทํ ๊ฐ๋ ์ด๋ฏ๋ก, ๋ณธ ๊ฒ์๊ธ์์ ์ด์ ๊ฒ์๊ธ๊ณผ ์ค๋ณต๋๋ ์ค๋ช ์ ์ต์ํ์ผ๋ก ์ค์๋ค.
#2 lifecycle-run-ktx ๋ผ์ด๋ธ๋ฌ๋ฆฌ
#2-1 ๊ฐ์
์๋ช ์ฃผ๊ธฐ ์ธ์ ๊ตฌ์ฑ์์๋ก Kotlin ์ฝ๋ฃจํด ์ฌ์ฉ | Android ๊ฐ๋ฐ์ | Android Developers
์ด ํ์ด์ง๋ Cloud Translation API๋ฅผ ํตํด ๋ฒ์ญ๋์์ต๋๋ค. ์๋ช ์ฃผ๊ธฐ ์ธ์ ๊ตฌ์ฑ์์๋ก Kotlin ์ฝ๋ฃจํด ์ฌ์ฉ ์ปฌ๋ ์ ์ ์ฌ์ฉํด ์ ๋ฆฌํ๊ธฐ ๋ด ํ๊ฒฝ์ค์ ์ ๊ธฐ์ค์ผ๋ก ์ฝํ ์ธ ๋ฅผ ์ ์ฅํ๊ณ ๋ถ๋ฅํ์ธ์. Kotlin ์ฝ
developer.android.com
์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ LifecycleScope๋ฅผ ์ด์ฉํด์ ์์ฉ๊ตฌ ์ฝ๋๋ฅผ ์ ๊ฑฐํ๋ค.
#2-2 androidx.lifecycle.LifecycleOwner.kt ์ดํด๋ณด๊ธฐ (LifecycleScope์ lifecycleScope)
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.lifecycle
import kotlinx.coroutines.CoroutineScope
/**
* A class that has an Android lifecycle. These events can be used by custom components to
* handle lifecycle changes without implementing any code inside the Activity or the Fragment.
*
* @see Lifecycle
* @see ViewTreeLifecycleOwner
*/
public interface LifecycleOwner {
/**
* Returns the Lifecycle of the provider.
*
* @return The lifecycle of the provider.
*/
public val lifecycle: Lifecycle
}
/**
* [CoroutineScope] tied to this [LifecycleOwner]'s [Lifecycle].
*
* This scope will be cancelled when the [Lifecycle] is destroyed.
*
* This scope is bound to
* [Dispatchers.Main.immediate][kotlinx.coroutines.MainCoroutineDispatcher.immediate].
*/
public val LifecycleOwner.lifecycleScope: LifecycleCoroutineScope
get() = lifecycle.coroutineScope
LifecycleScope๋ LifecycleOwner ์ธํฐํ์ด์ค์ ๊ตฌํ ๊ฐ์ฒด์ ์ข ์๋์ด, ํด๋น ๊ฐ์ฒด๋ค์ด ์๋ฉธํ ๋ ์์์ ์ข ๋ฃ๋๋ CoroutineScope๋ค. #3-1์์์ฒ๋ผ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ถ๋ฌ์จ ์๊ฐ๋ถํฐ LifecycleScope๋ LifecycleOwner์ ํ๋กํผํฐ๋ก์ ์๋ ์์ฑ๋๋ค. ํด๋น ํ๋กํผํฐ์ ์ด๋ฆ์ ์ฒซ ๊ธ์๊ฐ ์๋ฌธ์์ธ, lifecycleScope๋ค. lifecycleScope๋ coroutineScope์ ๋น์ทํ๊ฒ ์ฌ์ฉํ๋ฉด ๋๋ค.
#3 LifecycleScope ์ฌ์ฉํ๊ธฐ
#3-1 build.gradle.kts (Module)์์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ค์ด๋ก๋
plugins {
...
}
android {
...
}
dependencies {
...
// LifecycleScope
val lifecycle_version = "2.6.2"
implementation ("androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version")
}
์ฌ๊ธฐ์ ๊ตฌ๋ฌธ์ ๋ณต์ฌํด ๋ชจ๋ ์์ค ๊ทธ๋๋ค ํ์ผ์ ๋ถ์ฌ๋ฃ๋๋ค.
#3-2 MainActivity.kt
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
lifecycleScope.launch {
while (true) {
Log.i("interfacer_han", "I'm Coroutines")
delay(1000)
}
}
}
}
์ ์ฝ๋์ ์ฝ๋ฃจํด์ ํด๋น Activity๊ฐ onDestory()๋๋ฉด ์์์ ์ข ๋ฃ๋๋ค.
Fragment๋ Activity์ฒ๋ผ LifecycleOwner์ ๊ตฌํ์ฒด์ด๋ฏ๋ก, lifecycleScope๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
ViewModel๋ ๋ทฐ๋ชจ๋ธ ๋ง์ ์๋ช ์ฃผ๊ธฐ๊ฐ ์์ง๋ง LifecycleOwner ์ธํฐํ์ด์ค์ ๊ตฌํ์ฒด๋ ์๋๊ธฐ ๋๋ฌธ์ ViewModel์ lifecycleScope ํ๋กํผํฐ๋ฅผ ๊ฐ์ง์ง ์๊ณ , ๋ฐ๋ผ์ ์ฌ์ฉํ ์๋ ์๋ค. ๋์ ViewModel์ ์ํ ViewModelScope๊ฐ ์๋ค.
#3-3 repeatOnLifecycle()
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import kotlinx.coroutines.launch
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
Log.i("interfacer_han", "MainActivity.onCreate()")
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
lifecycleScope.launch {
lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
Log.i("interfacer_han", "(lifecycleScope) repeat when onStart()")
}
}
}
override fun onStart() {
Log.i("interfacer_han", "MainActivity.onStart()")
super.onStart()
}
override fun onResume() {
Log.i("interfacer_han", "MainActivity.onResume()")
super.onResume()
}
override fun onPause() {
Log.i("interfacer_han", "MainActivity.onPause()")
super.onPause()
}
override fun onStop() {
Log.i("interfacer_han", "MainActivity.onStop()")
super.onStop()
}
override fun onRestart() {
Log.i("interfacer_han", "MainActivity.onRestart()")
super.onRestart()
}
override fun onDestroy() {
Log.i("interfacer_han", "MainActivity.onDestroy()")
super.onDestroy()
}
}
/* Log ์ถ๋ ฅ ๊ฒฐ๊ณผ - ์ฑ ์ต์ด ์คํ ์
MainActivity.onCreate()
MainActivity.onStart()
(lifecycleScope) repeat when onStart()
MainActivity.onResume()
*/
/* Log ์ถ๋ ฅ ๊ฒฐ๊ณผ - ์ฑ์ ๋ฒ์ด๋ฌ์ ๋
MainActivity.onPause()
MainActivity.onStop()
*/
/* Log ์ถ๋ ฅ ๊ฒฐ๊ณผ - ์ฑ์ ์ฌ์ง์
ํ์ ๋
MainActivity.onRestart()
MainActivity.onStart()
(lifecycleScope) repeat when onStart()
MainActivity.onResume()
*/
์ ์ฝ๋๋ ์ด ๊ฒ์๊ธ์ #3-1์ ์ฐธ์กฐํด ์งฐ๋ค. LifecycleOwner์์ ์ฐ์ด๋ ์ฝ๋ฃจํด์ด ์๋ช ์ฃผ๊ธฐ์ ์ข ๋ ๋ํ ์ผํ๊ฒ ๋ฐ์ํ๊ฒ ๋ง๋ค๊ณ ์ถ์ ์ ์๋ค. ์ด๋ด ๋, repeatOnLifecycle()์ ์ฌ์ฉํ๋ค. ์ด์ฉ๋ฉด ์ด repeatOnLifecycle()์ด์ผ๋ง๋ก LifecycleScope์ ์ง๊ฐ๋ผ๊ณ ๋ณผ ์ ์๋ค. ์๋ํ๋ฉด LifecycleOwner ์๋ช ์ฃผ๊ธฐ์ ๊ฐ ๋จ๊ณ์์ ์์๋ ์ฝ๋ฃจํด์ ์ฝ๊ฒ ๊ตฌํํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค. (์ข ๋ฃ๋ ๋ง์ฐฌ๊ฐ์ง๋ก LifecycleOwner๊ฐ ํ๊ดด๋ ๋ ์ํ๋๋ค). ์์ ์ฝ๋์์ Lifecycle.State๋ฅผ Started๋ก ์ค์ ํ์ผ๋ฏ๋ก, onStart()์ผ ๋ ์ํ๋๋ค. ์ด์ฒ๋ผ repeateOnLifecycle()๊ฐ ์ฐ์ด๋ฉด ์ข ๋ ์ข์ ๋ฒ์, ๊ตญ์์ ์ธ ๋ฒ์ ์ lifecycleScope๊ฐ ๋๋ค.
#3-4 repeatOnLifecycle()์ ์กด์ฌ ์ด์ ์ถ์ธก
ํ์ง๋ง, #3-3์์ ์๋ฌธ์ ์ด ํ๋ ์๊ธด๋ค. ๊ตณ์ด repeatOnLifecycle()๋ฅผ ์ธ ๊ฒ ์๋๋ผ, ๊ทธ๋ฅ ์๋์ ๊ฐ์ ์ฝ๋๋ฅผ ์ฐ๋ฉด ๊ทธ๋ง ์๋๊ฐ?
...
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
Log.i("interfacer_han", "MainActivity.onCreate()")
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
...
override fun onStart() {
Log.i("interfacer_han", "MainActivity.onStart()")
super.onStart()
lifecycleScope.launch {
Log.i("interfacer_han", "(lifecycleScope) repeat when onStart()")
}
}
...
}
/* Log ์ถ๋ ฅ ๊ฒฐ๊ณผ - ์ฑ ์ต์ด ์คํ ์
MainActivity.onCreate()
MainActivity.onStart()
(lifecycleScope) repeat when onStart()
MainActivity.onResume()
*/
/* Log ์ถ๋ ฅ ๊ฒฐ๊ณผ - ์ฑ์ ๋ฒ์ด๋ฌ์ ๋
MainActivity.onPause()
MainActivity.onStop()
*/
/* Log ์ถ๋ ฅ ๊ฒฐ๊ณผ - ์ฑ์ ์ฌ์ง์
ํ์ ๋
MainActivity.onRestart()
MainActivity.onStart()
(lifecycleScope) repeat when onStart()
MainActivity.onResume()
*/
์ถ๋ ฅ ๊ฒฐ๊ณผ๊ฐ #3-3๊ณผ ๋๊ฐ๋ค. ๊ฐ์ ์ฝ๋๋ผ๋ ๋ง์ด๋ค. ๊ทธ๋ ๋ค๋ฉด repeatOnLifecycle()๊ฐ ๊ตณ์ด ์กด์ฌํ๋ ์ด์ ๋ ๋ฌด์์ธ๊ฐ? ์ฌ์ค ๋๋ ์ ๋ชจ๋ฅด๊ฒ ๋ค. ์๋ง๋, ๊ฐ Lifecycle.State์ ์ด๋ค ์ฝ๋ฃจํด์ด ์ํ๋ ์ง (๊ฐ๋ ์ฑ ์ข๊ฒ) ๋ชจ์์ ๋ณผ ์ ์๋ค๋ ์ ์ผ๋ก ์ถ์ธก๋๋ค.
#4 ์์ฝ
LifecycleOwner์์์ CoroutineScope ์์ฑ ๋ฐ Cancellation์ ์์ํํ๋ค.
#5 ์์ฑ๋ ์ฑ
android-practice/coroutines/LifecycleScope at master ยท Kanmanemone/android-practice
Contribute to Kanmanemone/android-practice development by creating an account on GitHub.
github.com
'๊นจ์ ๊ฐ๋ ๐ > Android' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
์ฐธ[Android] Room - ๊ธฐ์ด, INSERT์ DELETE ์ฐ์ต (0) | 2024.02.23 |
---|---|
[Kotlin] Coroutines - LiveData Builder (0) | 2024.02.22 |
[Android] RecyclerView - Adapter์ ์ธ์(Argument) ์ ๋ฌ (0) | 2024.02.03 |
[Android] RecyclerView - ๊ธฐ์ด (0) | 2024.02.02 |
[Android] Navigation - ์ ๋๋ฉ์ด์ (1) | 2024.01.27 |