Ejemplo de StateFlow en Kotlin Android


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.

Anuncio publicitario

Publicado por Codelaby

Mobile DevDesigner

Deja una respuesta

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Salir /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Salir /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Salir /  Cambiar )

Conectando a %s

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

A %d blogueros les gusta esto: