본문 바로가기

빈 구멍 채우기

[Kotlin Coroutine] launch 안 hot flow와 suspend function 사용 / launch 안에서 api 호출 누락

launch안에 paging3의 adapter의 loadStateFlow를 따라 ui 및 에러처리를 하고, viewModel에서 api를 호출해 pager로 데이터를 flow로 가져오도록 했었다.

 

그런데 flow가 호출되지 않는 것을 이제야 확인했다.

 

문제의 코드

launch{
    adapter.loadStateFlow.collectLatest { state ->
    	when(state.refresh) {
            is LoadState.NotLoading -> { ... }
            is LoadState.Error -> { ... }
            else -> Unit
        }
    } //<--2
    
    viewModel.flow.collectLatest {
    	adapter.submitData(it)
    } //<-- 1
}

 

개발 당시의 개발 및 테스트 순서가

1. flow 호출

2. empty view 및 에러처리

였었고...

 

2를 확인한 이후에 1를 다시 확인할 생각을 못 했었다. 

그리고 오늘에서야 1이 동작하지 않는다는 것을 알았다.

 

수정 코드

launch{
    adapter.loadStateFlow.collectLatest { state ->
    	when(state.refresh) {
            is LoadState.NotLoading -> { ... }
            is LoadState.Error -> { ... }
            else -> Unit
        }
    }
    
    //이 로그는 호출되지 않는다.
    Log.d("Test", "---------")
}

launch {
    viewModel.flow.collectLatest {
    	adapter.submitData(it)
    }
}

 

이슈가 발생한 이유가 무엇일까.... 추측해보자면

 

코드를 간략하게 다음과 같이 A,B로 나타낼 수 있다.

launch{
    adapter.loadStateFlow.collectLatest { state -> ... } //<--A
    viewModel.flow.collectLatest { ... } //<-- B
}

1) Flow<T>.collectLatest()는 suspend function이다. -> A,B 순차적으로 실행될 것이다.

 

2) A의 adapter, 즉 PagingDataAdapter의 loadStateFlow는 hot flow이다.

 

결론 : hot flow를 구독하고 있는 collectLatest는 계속 구독 중이므로 끝나지 않는다. A는 끝나지 않고 B가 실행될 차례는 돌아오지 않는다.