Android 如何使用NetworkBoundResource在MVVM中使用网络错误响应更新UI

Android 如何使用NetworkBoundResource在MVVM中使用网络错误响应更新UI,android,mvvm,rx-java,android-architecture-components,Android,Mvvm,Rx Java,Android Architecture Components,我试图在NetworkBoundResource中使用rxjava,同时使用谷歌的android架构组件实现MVVM模式。然而,我很难找到一种方法来将错误响应从网络调用传递到活动。 这里是一个链接到原来的 我读过这篇关于“”的文章,但仍然不清楚如何实际解决这个问题。 如果您能指导我使用基于代码的解决方案来更好地理解此场景,我将不胜感激 干杯 GithubRepository: @Singleton public class GithubRepository { private Gith

我试图在
NetworkBoundResource
中使用rxjava,同时使用谷歌的android架构组件实现MVVM模式。然而,我很难找到一种方法来将错误响应从网络调用传递到活动。 这里是一个链接到原来的

我读过这篇关于“”的文章,但仍然不清楚如何实际解决这个问题。 如果您能指导我使用基于代码的解决方案来更好地理解此场景,我将不胜感激

干杯

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

...
}
GitubListViewModel

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

在MVVM中,视图(您的活动)需要观察/订阅/收听模型。因此,当您在
ViewModel
中调用
getRepositories.subscribe
时,您需要让活动观察数据更改并获得回调。因此,在本例中,活动调用的是函数
gitublistviewmodel
。然后调用
repository.getRepositories().subscribe
。此外,我还使用LiveData监视数据更改。你能给我举个例子,说明如何监控活动中的请求状态,或者告诉我一个示例吗。Thanksupdatethelivedata,然后使用您需要的数据need@Blundell嗨,很抱歉给你添麻烦,我很难解决这个问题。如果您能给出一个基于代码的答案,我将不胜感激。这会有很大帮助。谢谢,我已经用所有相关细节更新了帖子。我建议你用尽可能小的代码创建一个新项目来重现这个问题。从活动中的一个可观察对象开始,然后添加错误,然后重新定位等,直到您理解每个部分