TIL : Compse ViewModel LiveData,StateFlow를 State로 변환하기

김성환·2024년 7월 21일

안드로이드 Compose에서 화면을 업데이트하려면 State의 값이 변경되거나 함수의 매개변수가 바뀌어야 합니다. 이때 Compose는 해당 변경사항을 감지하고 Recompose를 통해 UI를 업데이트합니다. 이 과정에서 사용하는 State는 Compose에 특화되어 있으며, 이러한 State를 사용하면 더 자연스럽고 효율적인 화면 갱신이 가능합니다.

안드로이드에서는 ViewModel에서 사용하는 LiveData나 StateFlow를 직접 Compose에서 State로 변환하여 사용하는 것을 권장합니다. 이렇게 하면 Compose와 ViewModel 간의 데이터 흐름이 더 원활해지고, LiveData나 StateFlow를 관찰하기 위한 별도의 observe나 collect 함수를 사용할 필요가 없어집니다.

이렇게 생각할수도 있습니다. 매개변수로 Recompose가된다면 굳이 State로 변환하지않고도 collect랑 observe만으로 수행할수있지 않을까 라고 말입니다.

사실 collect랑 observe를 이용하여 구현할수도 있습니다. 그렇지만 이러한로직이 사실은 State로 변환하는 내부 로직을 보면 큰 차이가 없습니다.

  • LiveData.observeAsState(initial: R): State
@Composable
fun <R, T : R> LiveData<T>.observeAsState(initial: R): State<R> {
    val lifecycleOwner = LocalLifecycleOwner.current
    val state = remember {
        @Suppress("UNCHECKED_CAST") /* Initialized values of a LiveData<T> must be a T */
        mutableStateOf(if (isInitialized) value as T else initial)
    }
    DisposableEffect(this, lifecycleOwner) {
        val observer = Observer<T> { state.value = it }
        observe(lifecycleOwner, observer)
        onDispose { removeObserver(observer) }
    }
    return state
}
  • Flow.collectAsState(initial: R,context: CoroutineContext = EmptyCoroutineContext): State
@Composable
fun <T : R, R> Flow<T>.collectAsState(
    initial: R,
    context: CoroutineContext = EmptyCoroutineContext
): State<R> = produceState(initial, this, context) {
    if (context == EmptyCoroutineContext) {
        collect { value = it }
    } else withContext(context) {
        collect { value = it }
    }
}

이 코드는 androidx.compose.runtime:runtime-livedata에서 제공하는 변환 함수입니다. collect의 경우 비동기 함수이기때문에 코루틴에서 사용해야됩니다. compose에서 사용할경우 SideEffect를 이용하여 구현하게되는데 위처럼 produceState를 이용하여 구현할수 있습니다. 굳이 Compose에서 직접 collect나 observe를 이용하여 얻을수있는 이점이 거의 없기에 State로 변환하는 것이 좋습니다.

0개의 댓글