A continuación un ejemplo de como implementar StateFlow usando Kotlin para Android, el caso práctico tiene en cuenta el estado de retorno (Loading, Error, Susccess)
Dependencias Flow para Android
Añadir las siguientes dependencias para usar Flow
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.0'
Resource Pattern
Clase sellada para los retornos del flow
sealed class MyUIState {
object FirstLoading : MyUIState()
object Loading : MyUIState()
data class Success(val data: String) : MyUIState()
data class Error(val exception: Throwable): MyUIState()
}
DataSource con Flow
Origen de los datos, en este caso es un generador de números aleatorios y un lanzador de error en caso si sale 0 o más de 20
private fun doLongRunningTask(): Flow<Int> {
return flow {
delay(1000L)
val randomNumber = (0..20).random()
if (randomNumber == 0) {
throw IOException()
} else if (randomNumber + 1 > 20) {
throw IndexOutOfBoundsException()
}
delay(2000L)
emit(randomNumber)
}
}
ViewModel con StateFlow
ViewModel para iniciar la obtención de los datos y encargado de subministrar los datos con el formato adecuado
class MyViewModel : ViewModel() {
private val _uiState: MutableStateFlow<MyUIState> = MutableStateFlow(MyUIState.Loading)
val uiState: MutableStateFlow<MyUIState> = _uiState
init {
fetchTaskContent()
}
fun fetchTaskContent() {
viewModelScope.launch {
doLongRunningTask()
.flowOn(Dispatchers.Default)
.onStart {
_uiState.value = MyUIState.Loading
}
.catch { e ->
_uiState.value = MyUIState.Error(e)
}
.collect {
_uiState.value = MyUIState.Success(it.toString())
}
}
}
...
DataCollect
Recolector del contenido mediante un observador del Flow
viewLifecycleOwner.lifecycleScope.launch {
mViewModel.uiState.collect {
when (it) {
is MyUIState.Loading -> {
Log.i(TAG, "setupObservers: LOADING")
}
is MyUIState.Error -> {
Log.e(TAG, "setupObservers: ERROR" + it.exception)
}
is MyUIState.Success -> {
val data = it.data
Log.d(TAG, "setupObservers: SUCCESS $data")
}
}
}
}
Resultado
Cada vez que se pulsa el botón se obtiene un número aleatorio antes de doto el estado de retorno será Loading y Susscess en recibir un número aleatorio válido y Error cuando algo ha fallado.