경험의 기록

2022.03.08 - [Android/AAC, MVVM] - [Android] 코루틴 StateFlow, SharedFlow 사용하기 (vs LiveData)

 

[Android] 코루틴 StateFlow, SharedFlow 사용하기 (vs LiveData)

2021.05.13 - [Android/AAC, MVVM] - [Android] Room + LiveData + ViewModel + DataBinding 사용하여 MVVM 패턴 사용하기 [Android] Room + LiveData + ViewModel + DataBinding 사용하여 MVVM 패턴 사용하기 202..

hanyeop.tistory.com

 

안드로이드에서 비동기처리를 위해 코루틴을 사용할 때,

LiveData 대신 Flow를 사용할 수 있다.

하지만 Flow는 스스로 라이프사이클을 알지 못하기 때문에

CoroutineScope 를 잘 이해하고 사용하여 불필요한 메모리 사용을 방지해야 한다.

 


1️⃣ viewModelScope.launch

class MainViewModel: ViewModel() {

    private val _countFlow = MutableSharedFlow<Int>()
    val countFlow get() = _countFlow.asSharedFlow()

    fun startCounting(){
        viewModelScope.launch(Dispatchers.IO) {
            for(i in 1 .. 10){
                _countFlow.emit(i)
                Log.d(TAG, "startCounting: $i")
                delay(1000L)
            }
        }
    }
}

viewModelScope를 통해 ViewModel 의 라이프사이클에 맞게 코루틴을 시작, 취소할 수 있다.

ViewModel이 파괴되지 않는한 백그라운드에서도 진행된다.

 

2️⃣ lifecycleScope.launch

// 백그라운드에서도 계속 코루틴이 진행된다.
lifecycleScope.launch {
    mainViewModel.countFlow.collectLatest {
        Log.d(TAG, "Activity: $it")
    }
}

이제 1번에서 확인한 뷰모델의 Flow를 Collect 해보자.

위처럼 코루틴 진행 중 백그라운드로 이동 (onStop) 하더라도

뷰모델의 작업이 진행되고, 액티비티에서 데이터 수집 또한 계속되고 있는 것을 확인할 수 있다.

둘 다 백그라운드에서도 계속해야 하는 작업이 아니라면 불필요한 메모리 사용이 발생한다.

 

 

3️⃣ lifecycleScope.launchWhenStarted

// 백그라운드로 나가면 코루틴 일시 정지, 돌아오면 다시 시작
lifecycleScope.launchWhenStarted {
    mainViewModel.countFlow.collectLatest {
        Log.d(TAG, "Activity: $it")
    }
}

lifecycleScope.launchWhenStarted 를 사용하면

코루틴 진행 중 백그라운드로 이동했을 때 뷰모델 작업이 정지되는 것을 확인할 수 있고

다시 화면으로 돌아오게 되면 정지된 이후 부분부터 작업이 재개되는 것을 확인할 수 있다.

 

4️⃣ repeatOnLifecycle

// 백그라운드로 나가면 코루틴 수집 정지, 돌아오면 시작
lifecycleScope.launch {
    repeatOnLifecycle(Lifecycle.State.STARTED) {
        mainViewModel.countFlow.collectLatest {
            Log.d("TEST123", "Activity: $it")
        }
    }
}

repeatOnLifecycle 를 사용하면

코루틴 진행 중 백그라운드로 이동했을 때 뷰모델 작업은 계속 진행되며 (viewModelScope)

액티비티의 데이터 수집만 정지 되었다가 다시 화면으로 돌아왔을 때 재개되는 것을 확인할 수 있다.

 

 

class MainActivity : AppCompatActivity() {

    private val flow: Flow<Int> = flow{
        for(i in 0 .. 1000){
            emit(i)
            delay(1000L)
        }
    }

    (..)
    
    // 백그라운드로 나가면 코루틴 취소, 돌아오면 처음부터 시작
    lifecycleScope.launch {
        repeatOnLifecycle(Lifecycle.State.STARTED) {
            flow.collectLatest {
                Log.d("TEST123", "Activity: $it")
            }
        }
    }
}

만약 위처럼 액티비티에서 진행되는 작업에 repeatOnLifecycle 사용할 경우

백그라운드로 이동 시 작업이 정지되며, 다시 화면으로 돌아오면 처음부터 다시 시작되는 것을 확인할 수 있다.


공부하며 작성한 내용이라 틀린 부분이 있을 수 있습니다.

틀린 부분이 있다면 말씀해주세요!

 

 

전체 코드

https://github.com/HanYeop/AndroidStudio-Practice2/tree/master/FlowLifeCycleEx

 

GitHub - HanYeop/AndroidStudio-Practice2: (2021.05.20~) 안드로이드 학습 내용 저장소

(2021.05.20~) 안드로이드 학습 내용 저장소. Contribute to HanYeop/AndroidStudio-Practice2 development by creating an account on GitHub.

github.com

 

반응형

공유하기

facebook twitter kakaoTalk kakaostory naver band
loading