LiveData를 StateFlow로 마이그레이션하지 않는 3가지 이유

StateFlow and SharedFlow documentation을 읽고, 보고, 검토한 후nowinandroid 소스 코드를 검토한 결과 LiveData를 StateFlow 또는 SharedFlow로 마이그레이션해야 할지 확신이 서지 않습니다. 적어도 지금은. 이유는 다음과 같습니다.

1. 대부분 원샷 수술만 한다.



Kotlin documentation에 따르면 흐름은 "순차적으로 값을 내보내고 정상적으로 완료되거나 예외가 있는 비동기 데이터 스트림"입니다.

주기적으로 서버에서 최신 데이터를 가져오거나 Room을 사용할 때 쿼리 결과의 실시간 업데이트를 받는 것과 같이 흐름을 사용하는 유효한 사용 사례가 있습니다.

그러나 대부분의 경우 일회성 작업만 수행하면 됩니다. 더도 말고 덜도 말고. 예를 들어, 서버에 GET 요청을 하고 데이터베이스에서 값을 검색합니다. 그러한 상황에서 내 작업의 본질은 흐름이 아닙니다. 흐름으로 변환할 수 있지만:

flow {
    val weather = weatherApi.getWeather(coordinate)
    emit(weather)
}


이것은 작동하지만 제 생각에는 특별한 이유없이 추가 코드 줄을 추가했습니다.

흐름 없이 StateFlow 또는 SharedFlow를 생성할 수도 있습니다.

private val _myState = MutableStateFlow(
    MyState(
        title = R.string.title,
        index = 0,
    )
)
val myState: StateFlow<MyState> = _myState.asStateFlow()


하지만 다시 말하지만, 여러 값을 순차적으로 내보내지 않는 경우 코드를 더 추가해야 하는 이유는 무엇입니까?

이것은 우리에게 두 번째 이유를 제공합니다.

2. LiveData는 수명 주기를 인식합니다.



StateFlow 및 SharedFlow는 Kotlin 라이브러리의 일부입니다. 플랫폼에 구애받지 않도록 설계되었으므로(go KMM! 🚀) Android 프레임워크와 수명 주기에 대해 알지 못합니다. Android에 통합하려면 Android 수명 주기를 따르는지 확인해야 합니다.

// Activity

lifecycleScope.launch {
    repeatOnLifecycle(Lifecycle.State.STARTED) {
        viewModel.uiState.collect { uiState ->
            when (uiState) {
                is UiState.Success -> showSuccess(uiState.data)
                is UiState.Error -> showError(uiState.exception)
            }
        }
    }
}


이를 위한 Jetpack 라이브러리만 있다면.. 🤔

그것이 바로 LiveData가 만든 것입니다! Android documentation에서 가져옴, "LiveData는 관찰 가능한 데이터 홀더 클래스입니다. 일반 관찰 가능과 달리 LiveData는 수명 주기를 인식합니다. 즉, 활동, 프래그먼트 또는 서비스와 같은 다른 앱 구성 요소의 수명 주기를 존중합니다."

이 코드로 동일한 기능을 수행할 수 있습니다.

// Activity

viewModel.uiState.observe(this) { uiState ->
    is UiState.Success -> showSuccess(uiState.data)
    is UiState.Error -> showError(uiState.exception)
}


LiveData를 사용하면 수명 주기를 수동으로 처리하고 메모리 누수를 걱정할 필요가 없으며 데이터가 항상 최신 상태인지 확인할 수 있습니다.

한 가지 주의할 점은 Compose에서 그 차이가 크지 않다는 것을 깨달았습니다(Jetpack 팀에게 찬사를 보냅니다 👏).

@Composable
fun HomeRoute(
    modifier: Modifier = Modifier,
    viewModel: MyViewModel = getViewModel<MyViewModel>()
) {
    val uiStateLiveData by viewModel.uiState.observeAsState(initial = UiState.Loading)
    val uiStateStateFlow by viewModel.uiState.collectAsStateWithLifecycle()
}


작년 Jetpack Compose is just released의 안정적인 버전. I do like writing UI using Compose 하지만 대부분의 회사에서 Compose를 채택하려면 아직 시간이 더 필요하다고 생각합니다.

3. StateFlow 또는 SharedFlow 기능이 필요하지 않습니다.



StateFlow 및 SharedFlow에는 방출된 요소를 구성하기 위한 많은 기능이 있습니다. SharedFlow에는 이전에 내보낸 값을 새 구독자에게 다시 보낼 수 있는 회신 기능이 있습니다. StateFlow에는 WhileSubscribed 클래스를 사용하여 업스트림 흐름을 중지하기 전에 시간 초과 메커니즘이 있습니다.

val uiState: StateFlow<UiState> = flow {
    emit(repository.getItem())
}.stateIn(
    scope = viewModelScope, 
    initialValue = UiState.Loading,
    started = WhileSubscribed(5_000),
)


흐름을 사용하면 여러 흐름을 StateFlow로 결합할 수도 있습니다.

val uiState: StateFlow<UiState> = combine(
    userRepository.getUser(),
    weatherRepository.getWeather(),
    statusRepository.getStatusStream(),
) { user, weather, status stream -> {
    // ...
}


반면 내 프로젝트에서 SharedFlow 및 StateFlow가 제공하는 멋진 기능은 있으면 좋은 것이지 필수가 아닙니다. 복잡한 작업은 Repository(데이터 계층) 또는 UseCases(도메인 계층)과 같은 다른 클래스에서 처리됩니다.

네트워크 및 데이터베이스와 같은 여러 데이터 소스를 병합하기 위해 RepositoryNetworkDataSources로 뒷받침되는 DbDataSources를 사용할 수 있습니다. 데이터 조작을 위해 Kotlin의 컬렉션에는 많은 유용한 기능(map, reduce, groupBy, count 등)이 있습니다. 데이터를 한 번만 내보낼 수 있도록 하려면 LiveData를 간단히 수정하는 것으로 충분합니다(SingleLiveData

요약



그렇다면 StateFlow와 SharedFlow는 언제 사용해야 할까요? 필요한 경우! 올바른 작업에 올바른 도구를 사용하십시오.

흐름 요소를 저장하거나 버퍼링해야 하는 경우, 프로젝트에서 KMM을 지원해야 하는 경우 또는 스트림 작업에 대한 최고 수준의 지원이 필요한 경우 StateFlow 및 SharedFlow 🙏를 사용하십시오.

LiveData가 충분하다고 생각한다면 아직 StateFlow로 마이그레이션하지 마세요 😁

참조



Unsplash에서 Samuel이 촬영한 이미지: https://unsplash.com/photos/scUBcasSvbE

좋은 웹페이지 즐겨찾기