Как обрабатывать состояния ошибок с помощью LiveData?

Новые LiveData могут использоваться в качестве замены наблюдаемых RxJava в некоторых сценариях. Однако, в отличие от Observable , LiveData не имеет обратного вызова для ошибок.

Мой вопрос: как я должен обрабатывать ошибки в LiveData , например, когда он поддерживается каким-то сетевым ресурсом, который может не получить из-за IOException ?

    В одном из примеров приложений Google для компонентов архитектуры Android они переносят выделенный объект LiveData в класс, который может содержать статус, данные и сообщение для испущенного объекта.

    https://github.com/googlesamples/android-architecture-components/blob/master/GithubBrowserSample/app/src/main/java/com/android/example/github/vo/Resource.java

    При таком подходе вы можете использовать статус, чтобы определить, была ли ошибка.

    Оберните данные, которые вы возвращаете из LiveData с какой-то ошибкой.

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

    // Теперь в вашем классе LifecycleRegistryOwner

     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 } }); 

    Просто поймайте Exception или выбросите его. Используйте объект Error для передачи этих данных в пользовательский интерфейс.

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

    В моем приложении мне пришлось перевести RxJava Observables в LiveData. При этом я, конечно, должен был поддерживать состояние ошибки. Вот как я это сделал (Котлин)

     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({ value = LiveDataResult(it, null) }, { value = LiveDataResult(null, it) })) } override fun onInactive() { super.onInactive() disposable.clear() } } 

    Другой подход – использовать MediatorLiveData который будет использовать источники LiveData различного типа. Это позволит вам разделить каждое событие:

    Например:

     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 } } 

    В этом примере загрузка и ошибка LiveData начнет наблюдаться, как только у MediatorLiveData будут активные наблюдатели.