티스토리 뷰

Android/Coroutine

Android Coroutine - Scope

강태종 2022. 1. 7. 21:47

Scope

CoroutineBuilder(launch, async)를 생성하는 범위이다. CoroutineBuilder를 통해 만들어진 Coroutine들은 기본적으로 해당 ScopeContext를 전달받는다. ScopeCoroutine을 만들 수 있는 범위이며, cancel같은 함수로 해당 ScopeCoroutine을 관리할 수 있다.

 

val scope = CoroutineScope(Dispatchers.IO)
val job = scope.launch {
    // 기본적으로 스코프의 Context 영향을 받는다. (IO)
    launch {
        // 상위 스코프의 Context를 가져온다. (IO)
    }
    
    launch(Dispatchers.Main) {
        // Context를 재정의 할 수 있다. (Main)
    }
}

// 해당 스코프의 Coroutine을 종료한다.
scope.cancel()

 

CoroutineScope

기본적으로 CoroutineScope는 Interface로 선언됐다. CoroutineScope라는 public function을 호출하여 CoroutineScope를 만들 수 있으며 매개변수로 CoroutineContext를 제공하여 만들 수 있다. 기본적으로 Scope내의 Coroutine이 모두 완료되기 전까지 완료되지 않습니다.

public interface CoroutineScope {
    /**
     * The context of this scope.
     * Context is encapsulated by the scope and used for implementation of coroutine builders that are extensions on the scope.
     * Accessing this property in general code is not recommended for any purposes except accessing the [Job] instance for advanced usages.
     *
     * By convention, should contain an instance of a [job][Job] to enforce structured concurrency.
     */
    public val coroutineContext: CoroutineContext
}
@Suppress("FunctionName")
public fun CoroutineScope(context: CoroutineContext): CoroutineScope =
    ContextScope(if (context[Job] != null) context else context + Job())

 

MainScope

CoroutineScope에서 Dispatchers.Main이 추가된 함수이다. UI Thread에서 처리할 작업을 실행할 때 적합하다.

@Suppress("FunctionName")
public fun MainScope(): CoroutineScope = ContextScope(SupervisorJob() + Dispatchers.Main)

 

GlobalScope

CoroutineScope를 상속받고 있습니다. GlobalScope는 앱이 동작하는 동안 계속 살아있습니다. 실제로 public object로 Singleton 패턴으로 만들어졌으며 잘못된 사용은 메모리 누수로 이어질 수 있습니다. Android에서는 CoroutineScope와 MainScope의 사용을 권장하고 있습니다.

@DelicateCoroutinesApi
public object GlobalScope : CoroutineScope {
    /**
     * Returns [EmptyCoroutineContext].
     */
    override val coroutineContext: CoroutineContext
        get() = EmptyCoroutineContext
}

 

LifecycleScope

생명주기가 중요한 Android에서 제공하는 Scope입니다. CoroutineContext를 설정할 수 있으며 기본으로 Dispatchers.Main이 제공됩니다. Lifecycle이 destroy되는 경우 해당 Scope의 모든 Coroutine은 취소됩니다.

Activity, Fragment에서 사용할 수 있습니다. Fragment경우 View의 LifeCycle에 맞춘 ViewLifecycleScope도 제공합니다.

public val Lifecycle.coroutineScope: LifecycleCoroutineScope
    get() {
        while (true) {
            val existing = mInternalScopeRef.get() as LifecycleCoroutineScopeImpl?
            if (existing != null) {
                return existing
            }
            val newScope = LifecycleCoroutineScopeImpl(
                this,
                SupervisorJob() + Dispatchers.Main.immediate
            )
            if (mInternalScopeRef.compareAndSet(null, newScope)) {
                newScope.register()
                return newScope
            }
        }
    }
lifecycleScope.launchWhenCreated {
    Log.d("PASS", "Create : ${Thread.currentThread()}")
}

lifecycleScope.launchWhenStarted {
    Log.d("PASS", "Start : ${Thread.currentThread()}")
}

lifecycleScope.launchWhenResumed {
    Log.d("PASS", "Resume : ${Thread.currentThread()}")
}

lifecycleScope.launch {
    Log.d("PASS", "Launch : ${Thread.currentThread()}")
}
2022-01-07 21:00:47.457 17304-17304/? D/PASS: Create : Thread[main,5,main]
2022-01-07 21:00:47.465 17304-17304/? D/PASS: Start : Thread[main,5,main]
2022-01-07 21:00:47.475 17304-17304/? D/PASS: Resume : Thread[main,5,main]
2022-01-07 21:00:47.455 17304-17304/? D/PASS: Launch : Thread[main,5,main]

 

ViewModelScope

ViewModel의 생명주기에 맞는 ViewModelScope도 지원합니다. LifeCycleScope와 마찬가지로 Dispatchers를 지정할 수 있으며 지정하지 않는 경우 Dispatchers.Main이 제공됩니다.

public val ViewModel.viewModelScope: CoroutineScope
    get() {
        val scope: CoroutineScope? = this.getTag(JOB_KEY)
        if (scope != null) {
            return scope
        }
        return setTagIfAbsent(
            JOB_KEY,
            CloseableCoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
        )
    }

internal class CloseableCoroutineScope(context: CoroutineContext) : Closeable, CoroutineScope {
    override val coroutineContext: CoroutineContext = context

    override fun close() {
        coroutineContext.cancel()
    }
}
viewModelScope.launch { 
    
}

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

Android Coroutine - Job Lifecycle  (0) 2022.01.15
Android Coroutine - Cancel  (0) 2022.01.08
Android Coroutine - Coroutine Builder  (0) 2022.01.07
Android Coroutine - CoroutineContext  (0) 2022.01.07
Android Coroutine - 개념  (0) 2022.01.04
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/02   »
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
글 보관함