在 Android 架构组件发布之前,我开始从事一个项目,其中我有自己的 ViewModel,它与 Fragment 具有相同的生命周期,并且 ViewModel 状态保存在 Loader 内的 StateObject 中,以便状态可以在方向变化中幸存。 ViewModel 通过接口与 Fragment 进行通信。这工作得很好,因为 ViewModel 和 Fragment 具有相同的生命周期。
我的 ViewModel 包含各种状态。它有一个 isLoading 布尔值、isEmptyStateVisible 布尔值等。每次状态更改时,我都会调用类似 view.notifyIsLoadingChanged(true/false) 的内容,在这种情况下,Fragment 将显示或隐藏微调器。
现在我将更改我的实现以将新的 ViewModel 与 LiveData 一起使用。实现 LiveData 的最快方法是更改 ViewModel 正在使用的 UI 界面的实现。所以我可以保留当前的实现并只添加此 UI 界面实现:
public class LiveDataProductReviewSheetUI extends LiveDataUI implements ProductReviewSheetUI {
public final MutableLiveData<ReviewViewModelState> ratingDescChanged = new MutableLiveData<>();
public final MutableLiveData<ReviewViewModelState> ratingChanged = new MutableLiveData<>();
public final MutableLiveData<ReviewViewModelState> reviewChanged = new MutableLiveData<>();
public final MutableLiveData<ReviewViewModelState> reviewValid = new MutableLiveData<>();
public final MutableLiveData<ReviewViewModelState> expandReview = new MutableLiveData<>();
public final MutableLiveData<ReviewViewModelState> reviewQuestion = new MutableLiveData<>();
public final MutableLiveData<ReviewViewModelState> reviewCreated = new MutableLiveData<>();
public final MutableLiveData<ReviewViewModelState> showMsg = new MutableLiveData<>();
public final MutableLiveData<ReviewViewModelState> dismiss = new MutableLiveData<>();
public void observe(LifecycleOwner owner, final ProductReviewSheetUI observer) {
ratingDescChanged.observe(owner, state -> observer.onRatingDescriptionChanged(state));
ratingChanged.observe(owner, state -> observer.onRatingChanged(state));
reviewChanged.observe(owner, state -> observer.onReviewChanged(state));
reviewValid.observe(owner, state -> observer.onHasValidReviewDataChanged(state));
expandReview.observe(owner, state -> observer.onExpandReviewFieldHasChanged(state));
reviewQuestion.observe(owner, state -> observer.onProductReviewQuestionChanged(state));
reviewCreated.observe(owner, state -> observer.onReviewCreated(state));
showMsg.observe(owner, state -> observer.onShowMessage(state));
dismiss.observe(owner, state -> observer.onCloseView());
}
@Override
public void onRatingDescriptionChanged(ReviewViewModelState state) {
ratingDescChanged.setValue(state);
}
@Override
public void onRatingChanged(ReviewViewModelState state) {
ratingChanged.setValue(state);
}
@Override
public void onReviewChanged(ReviewViewModelState state) {
reviewChanged.setValue(state);
}
@Override
public void onHasValidReviewDataChanged(ReviewViewModelState state) {
reviewValid.setValue(state);
}
@Override
public void onExpandReviewFieldHasChanged(ReviewViewModelState state) {
expandReview.setValue(state);
}
@Override
public void onProductReviewQuestionChanged(ReviewViewModelState state) {
reviewQuestion.setValue(state);
}
@Override
public void onReviewCreated(ReviewViewModelState state) {
reviewCreated.setValue(state);
}
@Override
public void onShowMessage(ReviewViewModelState state) {
showMsg.setValue(state);
}
@Override
public void onCloseView() {
dismiss.setValue(dismiss.getValue());
}
}
该类扩展的 LiveDataUI 类具有更多方法,例如:
public final MutableLiveData<Boolean> showLoading = new MutableLiveData<>();
public final MutableLiveData<Boolean> showEmptyState = new MutableLiveData<>();
通过这个实现,我最终会得到很多 MutableLiveData 对象,但感觉不太对劲。我是否在 ViewModel 中放入了太多状态?我的想法是将所有逻辑放在 ViewModel 中,以便我可以编写测试,在加载数据时验证 isLoading 是否为 true,如果没有从 Api 返回数据,则 isEmptyState 为 true 等。
我还注意到,如果我调用 setValue(state);在很短的时间内多次调用同一个 MutableLiveData 对象,onChanged 方法仅被调用一次。那是对的吗?