架构组件刷新 LiveData
Architecture Components refresh LiveData
我正在努力寻找使用架构组件在 master-detail 视图上刷新数据的正确方法。我有一个 single-top master activity 可以显示最喜欢的电影列表。当我转到详细视图时,收藏夹中的 add/remove 电影并关闭详细视图,主视图的数据保持不同步。我在 onCreate 方法中初始化视图模型:
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
moviesViewModel = ViewModelProviders
.of(this, viewModelFactory)
.get(MoviesViewModel.class);
moviesViewModel.getMovies(FAVOURITES).observe(this, this::show);
}
视图模型也很简单:
@NonNull
LiveData<Resource<List<Movie>>> getMovies(Criterion criterion) {
movieRepository.fetchBy(criterion)
.doOnSubscribe(it -> moviesLiveData.setValue(Resource.loading()))
.subscribe(
movies -> moviesLiveData.setValue(Resource.success(movies)),
throwable -> moviesLiveData.setValue(Resource.error(throwable))
);
最简单的解决方案是在每次激活时强制刷新视图:
@Override
public void onResume() {
super.onResume();
moviesViewModel.getMovies(FAVOURITES).observe(this, this::show);
}
但我不太喜欢这种方法,因为它会在屏幕方向改变时以及 activity 来自背景时导致刷新。
也可以只在结果发生变化时才开始显示结果的详细信息 activity 并刷新数据,但我也不认为在反应式方法中应该这样做。
此外,我正在考虑在相关解析器中订阅数据库更改,并在每次数据更改时用新内容更新 Flowable,但我确信它是否会工作,因为当更改发生时实时数据观察器 (主视图)处于暂停模式,因此不会收到通知,对吗?
您也可以将 livedata 用于数据库,以便更新来自 db -> vm -> ui
的更改
您可以通过多种方式管理主视图的刷新。
- 对于这种情况,您可以使用共享的 ViewModel。如果主视图和详细视图都是片段,您所要做的就是使用相同的视图模型,传入 activity 或包含片段作为范围,例如
ViewModelProviders.of(parentFragment!!, viewModelFactory)
。然后您的 moviesLiveData
可以被主页面和详细页面观察到。 **请注意,最新版本的导航允许您通过将 ViewModel
绑定到特定导航图来更精细地定义范围。
- 如果您正在为您的页面使用活动,您可以通过
startActivityForResult
、setResult
在详细信息屏幕中将电影结果信息传回母版页,并在 onActivityResult
- 您可以在视图模型以外的地方缓存网络请求的结果。通常,您可能有一个 Singleton 存储库来检索您的数据。您可以按照与 ViewModels 相同的模式使用
LiveData
。
- 您也可以按照您的建议观察您的数据库。不要担心它处于暂停模式!这就是
LiveData
的要点,它存储最新更新并在有人观察到它时再次发送它。
我正在努力寻找使用架构组件在 master-detail 视图上刷新数据的正确方法。我有一个 single-top master activity 可以显示最喜欢的电影列表。当我转到详细视图时,收藏夹中的 add/remove 电影并关闭详细视图,主视图的数据保持不同步。我在 onCreate 方法中初始化视图模型:
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
moviesViewModel = ViewModelProviders
.of(this, viewModelFactory)
.get(MoviesViewModel.class);
moviesViewModel.getMovies(FAVOURITES).observe(this, this::show);
}
视图模型也很简单:
@NonNull
LiveData<Resource<List<Movie>>> getMovies(Criterion criterion) {
movieRepository.fetchBy(criterion)
.doOnSubscribe(it -> moviesLiveData.setValue(Resource.loading()))
.subscribe(
movies -> moviesLiveData.setValue(Resource.success(movies)),
throwable -> moviesLiveData.setValue(Resource.error(throwable))
);
最简单的解决方案是在每次激活时强制刷新视图:
@Override
public void onResume() {
super.onResume();
moviesViewModel.getMovies(FAVOURITES).observe(this, this::show);
}
但我不太喜欢这种方法,因为它会在屏幕方向改变时以及 activity 来自背景时导致刷新。
也可以只在结果发生变化时才开始显示结果的详细信息 activity 并刷新数据,但我也不认为在反应式方法中应该这样做。
此外,我正在考虑在相关解析器中订阅数据库更改,并在每次数据更改时用新内容更新 Flowable,但我确信它是否会工作,因为当更改发生时实时数据观察器 (主视图)处于暂停模式,因此不会收到通知,对吗?
您也可以将 livedata 用于数据库,以便更新来自 db -> vm -> ui
的更改您可以通过多种方式管理主视图的刷新。
- 对于这种情况,您可以使用共享的 ViewModel。如果主视图和详细视图都是片段,您所要做的就是使用相同的视图模型,传入 activity 或包含片段作为范围,例如
ViewModelProviders.of(parentFragment!!, viewModelFactory)
。然后您的moviesLiveData
可以被主页面和详细页面观察到。 **请注意,最新版本的导航允许您通过将ViewModel
绑定到特定导航图来更精细地定义范围。 - 如果您正在为您的页面使用活动,您可以通过
startActivityForResult
、setResult
在详细信息屏幕中将电影结果信息传回母版页,并在onActivityResult
- 您可以在视图模型以外的地方缓存网络请求的结果。通常,您可能有一个 Singleton 存储库来检索您的数据。您可以按照与 ViewModels 相同的模式使用
LiveData
。 - 您也可以按照您的建议观察您的数据库。不要担心它处于暂停模式!这就是
LiveData
的要点,它存储最新更新并在有人观察到它时再次发送它。