Coroutine이란?
- Co(협력)+Routine(하나의 태스크, 함수)
- Routine에는 두가지가 존재: Main Routine, Sub Routine
- Sub Routine은 Main에서 호출하는 시점에서 진입, return을 만나면 탈출
- Coroutine은 함수에 진입할 수 있는 진입점도 여러개, 빠져나가는 탈출점도 여러개
- return 문이나 마지막 닫는 괄호를 만나지 않더라도 언제든 나가고 들어갈 수 있음
// 스레드의 main 함수가 drawPerson()을 호출하면 하나의 코루틴 블럭(함수)이 생성됨
// drawPerson()은 언제든 진입, 탈출할 수 있는 자격이 주어짐
fun drawPerson() {
/* 실제로 startCoroutine은 없음. 직관적 이해를 위해 이 코드에서만 사용 */
startCoroutine {
// 코루틴 함수가 실행되는 과정에서 suspend 키워드를 가진 함수를 만나게 되면,
// 더이상 아래 코드를 실행하지 않고 멈춤(suspend) 후 코루틴 블럭 탈출
drawHead()
drawBody()
drawLegs()
// 다른 코드들이 실행되다가도, drawHead가 끝이나면
// 다시 코루틴으로 진입해 아까 멈춘 부분(drawHead) 아래부터 다시 실행됨
}
}
suspend fun drawHead() {
delay(2000)
}
suspend fun drawBody() {
delay(5000)
}
suspend fun drawLegs() {
delay(3000)
}
LifecycleScope란?
Kotlin 코루틴은 비동기 코드를 작성할 수 있게 하는 API를 제공함.
Kotlin 코루틴을 사용하면 코루틴이 실행되어야 하는 시기를 관리하는 데 도움이 되는 CoroutineScope를 정의할 수 있음
LifecycleScope는 각 Lifecycle 객체에서 정의됨.
이 범위에서 실행된 코루틴은 Lifecycle이 끝날 때 제거됨.
lifecycle.coroutineScope 또는 lifecycleOwner.lifecycleScope 속성을 통해 Lifecycle의 CoroutineScope에 엑섹스 가능
class MyFragment: Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewLifecycleOwner.lifecycleScope.launch {
val params = TextViewCompat.getTextMetricsParams(textView)
val precomputedText = withContext(Dispatchers.Default) {
PrecomputedTextCompat.create(longTextContent, params)
}
TextViewCompat.setPrecomputedText(textView, precomputedText)
}
}
}
재시작 가능한 수명 주기 인식 코루틴
Lifecycle과 LifecycleOwner는 실행 정지 repeatOnLifecycle API 제공
class MyFragment : Fragment() {
val viewModel: MyViewModel by viewModel()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// lifecycle coroutine 생성
viewLifecycleOwner.lifecycleScope.launch {
// repeatOnLifecycle launches the block in a new coroutine every time the
// lifecycle is in the STARTED state (or above) and cancels it when it's STOPPED.
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
// Trigger the flow and start listening for values.
// This happens when lifecycle is STARTED and stops
// collecting when the lifecycle is STOPPED
viewModel.someDataFlow.collect {
// Process item
}
}
}
}
}
수명주기 인식 코루틴 정지
Lifecycle은 lifecycle.whenCreated, lifecycle.whenStarted, lifecycle.whenResumed와 같은 추가 메서드 제공
-> 블록 내부에서 실행되는 코루틴은 Lifecycle이 원하는 최소한의 상태가 아니면 정지됨
class MyFragment: Fragment {
init { // Notice that we can safely launch in the constructor of the Fragment.
lifecycleScope.launch {
whenStarted {
// The block inside will run only when Lifecycle is at least STARTED.
// It will start executing when fragment is started and
// can call other suspend methods.
loadingView.visibility = View.VISIBLE
val canAccess = withContext(Dispatchers.IO) {
checkUserAccess()
}
// When checkUserAccess returns, the next line is automatically
// suspended if the Lifecycle is not *at least* STARTED.
// We could safely run fragment transactions because we know the
// code won't run unless the lifecycle is at least STARTED.
loadingView.visibility = View.GONE
if (canAccess == false) {
findNavController().popBackStack()
} else {
showContent()
}
}
// This line runs only after the whenStarted block above has completed.
}
}
}
코루틴이 활성 상태인 동안 when 메서드 중 하나를 통해 Lifecycle이 끝나면 코루틴은 자동 취소됨
class MyFragment: Fragment {
init {
lifecycleScope.launchWhenStarted {
try {
// Call some suspend functions.
} finally {
// This line might execute after Lifecycle is DESTROYED.
if (lifecycle.state >= STARTED) {
// Here, since we've checked, it is safe to run any
// Fragment transactions.
}
}
}
}
}
'Android > 도구 및 라이브러리' 카테고리의 다른 글
[Android]DeepLink와 Scheme (0) | 2023.05.29 |
---|---|
[Android/Async]RxJava에서 Throttle과 Debounce (0) | 2023.05.10 |
[Android]Deeplink (0) | 2023.02.25 |
[Android/Library]Eventbus (0) | 2023.02.24 |
[Android/Async]RxJava (0) | 2023.02.24 |