How to update UI with network error response in MVVM using NetworkBoundResource

穿精又带淫゛_ 提交于 2020-04-10 05:34:41

问题


I'm trying to implement MVVM pattern usingGoogle's android architecture components while using RX Java in NetworkBoundResource. However I'm having a difficult time finding a way to communicate the error response from network call to activity. here is a link to the original github project.

I have read this post about "Refactoring google's NetworkBoundResource class to use RxJava instead of LiveData" but still not clear how to actually solve the problem. would appreciate if you could direct me to a code based solution for this scenario for better understanding.

cheers!

GithubRepository:

@Singleton
public class GithubRepository {

    private GithubDao githubDao;
    private GithubApiService githubApiService;

    public GithubRepository(GithubDao githubDao, GithubApiService githubApiService) {
        this.githubDao = githubDao;
        this.githubApiService = githubApiService;
    }

    public Observable<Resource<List<GithubEntity>>> getRepositories(Long page) {
        return new NetworkBoundResource<List<GithubEntity>, GithubApiResponse>() {

            @Override
            protected void saveCallResult(@NonNull GithubApiResponse item) {
                List<GithubEntity> repositories = item.getItems();
                for (GithubEntity githubEntity : repositories) {
                    githubEntity.setPage(page);
                    githubEntity.setTotalPages(item.getTotalCount());
                }
                githubDao.insertRepositories(repositories);
            }

            @Override
            protected boolean shouldFetch() {
                return true;
            }

            @NonNull
            @Override
            protected Flowable<List<GithubEntity>> loadFromDb() {
                List<GithubEntity> repositories = githubDao.getRepositoriesByPage(page);
                return (repositories == null || repositories.isEmpty()) ?
                        Flowable.empty() : Flowable.just(repositories);
            }

            @NonNull
            @Override
            protected Observable<Resource<GithubApiResponse>> createCall() {
                return githubApiService.fetchRepositories(QUERY_SORT, QUERY_ORDER, page)
                        .flatMap(response ->
                                Observable.just(response.isSuccessful()
                                        ? Resource.success(response.body())
                                        : Resource.error("", new GithubApiResponse())));
            }

        }.getAsObservable();
    }
}

.:UPDATE:. So I can see that the the in NetworkBoundResource the doOnError and onErrorResumeNext are handling the error response. but i don't know how to get this response in the activity. I am having a hard time understanding it.

NetworkBoundResource:

public abstract class NetworkBoundResource<ResultType, RequestType> {

    private Observable<Resource<ResultType>> result;

    @MainThread
    protected NetworkBoundResource() {
        Observable<Resource<ResultType>> source;
        if (shouldFetch()) {
            source = createCall()
                    .subscribeOn(Schedulers.io())
                    .doOnNext(apiResponse -> saveCallResult(processResponse(apiResponse)))
                    .flatMap(apiResponse -> loadFromDb().toObservable().map(Resource::success))
                    .doOnError(t -> onFetchFailed())
                    .onErrorResumeNext(t -> {
                        return loadFromDb()
                                .toObservable()
                                .map(data -> Resource.error(t.getMessage(), data));

                    })
                    .observeOn(AndroidSchedulers.mainThread());
        } else {
            source = loadFromDb()
                    .toObservable()
                    .map(Resource::success);
        }

        result = Observable.concat(
                loadFromDb()
                        .toObservable()
                        .map(Resource::loading)
                        .take(1),
                source
        );
    }

    public Observable<Resource<ResultType>> getAsObservable() {return result;}

    protected void onFetchFailed() {}

    @WorkerThread
    protected RequestType processResponse(Resource<RequestType> response) {return response.data;}

    @WorkerThread
    protected abstract void saveCallResult(@NonNull RequestType item);

    @MainThread
    protected abstract boolean shouldFetch();

    @NonNull
    @MainThread
    protected abstract Flowable<ResultType> loadFromDb();

    @NonNull
    @MainThread
    protected abstract Observable<Resource<RequestType>> createCall();
}

GithubListViewModel:

public class GithubListViewModel extends ViewModel {

    private Long currentPage = 0l;
    private GithubRepository repository;

    private List<GithubEntity> repositories = new ArrayList<>();
    private SingleLiveEvent<List<GithubEntity>> repoListLiveData = new SingleLiveEvent<>();

    @Inject
    public GithubListViewModel(GithubDao githubDao, GithubApiService githubApiService) {
        repository = new GithubRepository(githubDao, githubApiService);
    }

    public void fetchRepositories() {
        repository.getRepositories(++currentPage)
                .subscribe(resource -> {
                    if(resource.isLoaded()) {
                        repositories.addAll(resource.data);
                        getRepositoryListLiveData().postValue(resource.data);
                    }
                });
    }


    public List<GithubEntity> getRepositories() {
        return repositories;
    }

    public SingleLiveEvent<List<GithubEntity>> getRepositoryListLiveData() {
        return repoListLiveData;
    }

    public boolean isLastPage() {
        return getRepositoryListLiveData().getValue() != null &&
                !getRepositoryListLiveData().getValue().isEmpty() ?
                getRepositoryListLiveData().getValue().get(0).isLastPage() :
                false;
    }
}

GithubActivity:

public class GithubListActivity extends AppCompatActivity implements RecyclerLayoutClickListener {

...

    private void initialiseViewModel() {
        githubListViewModel = ViewModelProviders.of(this, viewModelFactory).get(GithubListViewModel.class);
        githubListViewModel.getRepositoryListLiveData().observe(this, repositories -> {
            if(githubListAdapter.getItemCount() == 0) {
                if(!repositories.isEmpty()) {
                    animateView(repositories);

                } else displayEmptyView();

            } else if(!repositories.isEmpty()) displayDataView(repositories);
        });
    }
...

githubListViewModel.fetchRepositories();

...
}

来源:https://stackoverflow.com/questions/60466382/how-to-update-ui-with-network-error-response-in-mvvm-using-networkboundresource

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!