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嗨,很抱歉给你添麻烦,我很难解决这个问题。如果您能给出一个基于代码的答案,我将不胜感激。这会有很大帮助。谢谢,我已经用所有相关细节更新了帖子。我建议你用尽可能小的代码创建一个新项目来重现这个问题。从活动中的一个可观察对象开始,然后添加错误,然后重新定位等,直到您理解每个部分