githubbrowsersample example android android-architecture-components

githubbrowsersample - android architecture components example



¿Cómo manejar estados de error con LiveData? (5)

Ajustar los datos que devuelve de LiveData con algún tipo de mensaje de error

public class DataWrapper<T>T{ private T data; private ErrorObject error; //or A message String, Or whatever }

// Ahora en tu LifecycleRegistryOwner Class

LiveData<DataWrapper<SomeObjectClass>> result = modelView.getResult(); result.observe(this, newData ->{ if(newData.error != null){ //Can also have a Status Enum //Handle Error } else{ //Handle data } });

Simplemente capture una Exception lugar o tírela. use el Objeto de error para pasar estos Datos a la IU.

MutableLiveData<DataWrapper<SomObject>> liveData = new...; //On Exception catching: liveData.set(new DataWrapper(null, new ErrorObject(e));

El nuevo LiveData se puede usar como reemplazo de los observables de RxJava en algunos escenarios. Sin embargo, a diferencia de Observable , LiveData no tiene devolución de llamada por errores.

Mi pregunta es: ¿cómo debo manejar los errores en LiveData , por ejemplo, cuando está respaldado por algún recurso de red que no se puede recuperar debido a una IOException ?


En mi aplicación, tuve que traducir RxJava Observables a LiveData. Mientras hacía eso, por supuesto tuve que mantener el estado de error. Así es como lo hice (Kotlin)

class LiveDataResult<T>(val data: T?, val error: Throwable?) class LiveObservableData<T>(private val observable: Observable<T>) : LiveData<LiveDataResult<T>>() { private var disposable = CompositeDisposable() override fun onActive() { super.onActive() disposable.add(observable.subscribe({ postValue(LiveDataResult(it, null)) }, { postValue(LiveDataResult(null, it)) })) } override fun onInactive() { super.onInactive() disposable.clear() } }



He creado una aplicación de búsqueda de películas here en la que he usado diferentes objetos LiveData , uno para la respuesta exitosa de la red y otra para los fracasados:

private val resultListObservable = MutableLiveData<List<String>>() private val resultListErrorObservable = MutableLiveData<HttpException>() fun findAddress(address: String) { mainModel.fetchAddress(address)!!.subscribeOn(schedulersWrapper.io()).observeOn(schedulersWrapper.main()).subscribeWith(object : DisposableSingleObserver<List<MainModel.ResultEntity>?>() { override fun onSuccess(t: List<MainModel.ResultEntity>) { entityList = t resultListObservable.postValue(fetchItemTextFrom(t)) } override fun onError(e: Throwable) { resultListErrorObservable.postValue(e as HttpException) } }) }


Otro enfoque es usar MediatorLiveData que tomará las fuentes de LiveData de diferente tipo. Esto te dará separación de cada evento:

Por ejemplo:

open class BaseViewModel : ViewModel() { private val errorLiveData: MutableLiveData<Throwable> = MutableLiveData() private val loadingStateLiveData: MutableLiveData<Int> = MutableLiveData() lateinit var errorObserver: Observer<Throwable> lateinit var loadingObserver: Observer<Int> fun <T> fromPublisher(publisher: Publisher<T>): MediatorLiveData<T> { val mainLiveData = MediatorLiveData<T>() mainLiveData.addSource(errorLiveData, errorObserver) mainLiveData.addSource(loadingStateLiveData, loadingObserver) publisher.subscribe(object : Subscriber<T> { override fun onSubscribe(s: Subscription) { s.request(java.lang.Long.MAX_VALUE) loadingStateLiveData.postValue(LoadingState.LOADING) } override fun onNext(t: T) { mainLiveData.postValue(t) } override fun onError(t: Throwable) { errorLiveData.postValue(t) } override fun onComplete() { loadingStateLiveData.postValue(LoadingState.NOT_LOADING) } }) return mainLiveData } }

En este ejemplo, la carga y el error de LiveData comenzarán a observarse una vez que MediatorLiveData tenga observadores activos.