StateFlow는 코틀린에서 제공하는 Flow API의 일부입니다‼️
어떤 상태의 현재 값을 저장하고 있으며, 이 상태 값이 변경될 때마다 구독하고 있는 구성요소들에게 새로운 상태를 알릴 수 있는 기능을 가진 데이터 흐름🐳입니다.
간단히 말해, StateFlow는 특정 상태의 최신 값을 관찰하고, 이 값이 변경될 때마다 자동으로 업데이트를 알려주는 역할을 합니다. 이를 통해 코루틴과 함께 상태 관리를 보다 쉽고 효율적으로 할 수 있게 돕습니다.
LiveData는 UI와 긴밀한 데이터를, StateFlow는 보다 유연하게 사용해야 하는 데이터를 다룬다. 각각 상황에 맞게 쓰면 좋을 것 같다.
아래와 같이 viewModel을 만들고 dummyUseCase를 주입해서 사용하고 있음을 볼 수 있습니다.
onStart에선 로딩, catch에선 오류, collectLatest에서는 성공을 보내주고 있죠?!
사용 자체는 굉장히 쉽습니다. ☺️
@HiltViewModel
class MainViewModel @Inject constructor(
private val dummyUseCase: DummyUseCase
) : ViewModel() {
// 초기값도 야무지게 지정하는 모습을 볼 수 있죠?
private val _dummyUIState = MutableStateFlow<UIState<Dummy>>(UIState.Empty)
val dummyUIState: StateFlow<UIState<Dummy>> = _dummyUIState
private fun getDummy() {
// viewModelScope를 따라감
viewModelScope.launch {
dummyUseCase()
// 시작시
.onStart { _dummyUIState.update { UIState.Loading } }
// 오류시
.catch { e -> _dummyUIState.update { UIState.Error(e) } }
// 성공시
.collectLatest { value -> _dummyUIState.update { UIState.Success(value) } }
}
}
}
이렇게 만든 viewModel을 Activity에서 사용하는 과정을 볼까요?
다음과 같이 사용하면 됩니다 😎
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
private val mainViewModel: MainViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
lifecycleScope.launchWhenStarted {
mainViewModel.dummyUIState.collectLatest { state ->
when (state) {
is UIState.Loading -> {
Snackbar.make(binding.root, "로딩 중...", Snackbar.LENGTH_SHORT).show()
}
is UIState.Success -> {
Snackbar.make(binding.root, "성공 >_<", Snackbar.LENGTH_SHORT).show()
}
is UIState.Error -> {
Snackbar.make(binding.root, "오류 -_-", Snackbar.LENGTH_SHORT).show()
}
}
}
}
}
위 코드에서 상태에 따라 스낵바를 띄워주는 모습을 볼 수 있습니다 ‼️
참 쉽죠? 😅
SharedFlow는 이벤트 전달이나 데이터 스트림의 다양한 처리에 더 적합하며, 특히 값을 보유하지 않는 이벤트 전송에 유리하다고 볼 수 있습니다 ‼️
항상 중요한 이야기지만 코딩에 정답은 없습니다 🤭
상황에 맞게 적절한 방식을 사용해 상태관리를 한다면, 여러분도 상태관리의 신이 될 수 있어요~~ 👍