如果MVVM是所有关于数据绑定,不能做的东西像view.doThis()
,否则它的MVP,那么如何调用视图上的动作?
假设我有一个具有snackbar
的视图。View
受ViewModel
控制。这个ViewModel
应该如何显示snackbar
而不去snackbar.show()
?
在MVVM中,ViewModel捕获视图的状态。View观察ViewModel的变化并更新自己。因此,View &ViewModel通过改变值来实现(与MVP中的方法调用相反)。
由于Snackbar
就像一个全局行为(如Toast),它可以在活动/片段级别实现。因此,您可以创建一个MessageHelper
接口,并将其作为依赖项传递给ViewModel。活动将实现它并显示Snackbar
。
的例子:
- 使用接口的ItemViewModel
- 实现接口的Activity基类
然而,可能有一些特定于视图的行为不能在Activity级别实现。对于这种情况,您可以使用databinding.Observable
来触发事件。例如,假设我们想要动画一个特定的视图。我们可以创建一个BindingAdapter
@BindingAdapter({"shakeTrigger"})
public static void showSnackbar(View view, Void trigger) {
// Do the animation here. You could add meaningful argument types to control the animation
}
在XML中,我们可以使用
<TextView
bind:shakeTrigger="@{vm.shakeTrigger}"/>
然后,在viewModel中,你可以使用数据绑定api触发震动。使用BaseObservable
的一种方法是:
public class ConfigurationViewModel extends BaseObservable implements ViewModel {
@Bindable
public final Void shakeTrigger = null;
public void shake() {
notifyPropertyChanged(BR.shakeTrigger);
}
}
如果您使用RxJava,触发器可以从rx.Observable
实现。您可以签出我的库来使用带有数据绑定的RxJava。https://github.com/manas-chaudhari/android-mvvm
简短的回答是你不知道,这实际上是一件好事。在MVVM中,ViewModel负责为视图准备和存储数据。它从模型中获取数据并让它准备好在视图上设置,但它不设置值,设置值和更新视图状态是视图本身的责任,MVVM中的视图监视数据的变化并更新自己。
这方面的一个例子是,当您的列表为空时显示一个空列表页面。要在MVVM中做到这一点,您可以在ViewModel中定义视图可见性的状态,我们将其称为emptyPageVisibility
,然后适当地更新此值。
public class PlaylistDetailViewModel extends ViewModel {
private MutableLiveData<Integer> emptyPageVisibility = new MutableLiveData<>();
private void someMethodInYourViewModel(){
emptyPageVisibility.setValue(View.VISIBLE);
}
}
然后在你的视图中,你观察这个,当这个数据改变时更新视图,像这样
viewModel.getEmptyPageVisibility().observe(this,
visibility -> emptyPageView.setVisibility(visibility));