How to handle error states with LiveData?

后端 未结 7 616
暗喜
暗喜 2020-12-07 14:10

The new LiveData can be used as a replacement for RxJava\'s observables in some scenarios. However, unlike Observable, LiveData has no callback for

7条回答
  •  悲&欢浪女
    2020-12-07 14:46

    You can extend from MutableLiveData and create a holder Model to wrap your data.

    This is your Wrapper Model

    public class StateData {
    
        @NonNull
        private DataStatus status;
    
        @Nullable
        private T data;
    
        @Nullable
        private Throwable error;
    
        public StateData() {
            this.status = DataStatus.CREATED;
            this.data = null;
            this.error = null;
        }
    
        public StateData loading() {
            this.status = DataStatus.LOADING;
            this.data = null;
            this.error = null;
            return this;
        }
    
        public StateData success(@NonNull T data) {
            this.status = DataStatus.SUCCESS;
            this.data = data;
            this.error = null;
            return this;
        }
    
        public StateData error(@NonNull Throwable error) {
            this.status = DataStatus.ERROR;
            this.data = null;
            this.error = error;
            return this;
        }
    
        public StateData complete() {
            this.status = DataStatus.COMPLETE;
            return this;
        }
    
        @NonNull
        public DataStatus getStatus() {
            return status;
        }
    
        @Nullable
        public T getData() {
            return data;
        }
    
        @Nullable
        public Throwable getError() {
            return error;
        }
    
        public enum DataStatus {
            CREATED,
            SUCCESS,
            ERROR,
            LOADING,
            COMPLETE
        }
    }
    

    This is your extended LiveData Object

    public class StateLiveData extends MutableLiveData> {
    
        /**
         * Use this to put the Data on a LOADING Status
         */
        public void postLoading() {
            postValue(new StateData().loading());
        }
    
        /**
         * Use this to put the Data on a ERROR DataStatus
         * @param throwable the error to be handled
         */
        public void postError(Throwable throwable) {
            postValue(new StateData().error(throwable));
        }
    
        /**
         * Use this to put the Data on a SUCCESS DataStatus
         * @param data
         */
        public void postSuccess(T data) {
            postValue(new StateData().success(data));
        }
    
        /**
         * Use this to put the Data on a COMPLETE DataStatus
         */
        public void postComplete() {
            postValue(new StateData().complete());
        }
    
    }
    

    And this is how you use it

    StateLiveData> bookListLiveData;
    bookListLiveData.postLoading();
    bookListLiveData.postSuccess(books);
    bookListLiveData.postError(e);
    

    And how it can be observed:

    private void observeBooks() {
            viewModel.getBookList().observe(this, this::handleBooks);
        }
    
        private void handleBooks(@NonNull StateData> books) {
          switch (stepIds.getStatus()) {
                case SUCCESS:
                    List bookList = books.getData();
                    //TODO: Do something with your book data
                    break;
                case ERROR:
                    Throwable e = books.getError();
                    //TODO: Do something with your error
                    break;
                case LOADING:
                    //TODO: Do Loading stuff
                    break;
                case COMPLETE:
                    //TODO: Do complete stuff if necessary
                    break;
            }
        }
    

提交回复
热议问题