【问题标题】:Are actions allowed in MVVM? AndroidMVVM 中是否允许执行操作?安卓
【发布时间】:2016-09-22 11:26:48
【问题描述】:

如果 MVVM 都是关于数据绑定的,不能做类似view.doThis() 的事情,否则它是 MVP,那么如何在视图上调用操作?

假设我有一个具有snackbar 的视图。 View 由其ViewModel 控制。这个ViewModel 应该如何显示snackbar 而不是snackbar.show()

【问题讨论】:

    标签: java android user-interface mvvm action


    【解决方案1】:

    在 MVVM 中,ViewModel 捕获视图的状态。 View 会观察 ViewModel 的变化并自行更新。因此,View 和 ViewModel 之间的通信是通过值的变化发生的(与 MVP 中的方法调用不同)。

    由于Snackbar 就像一个全局行为(如Toast),它可以在Activity/Fragment 级别实现。因此,您可以创建一个MessageHelper 接口并将其作为依赖项传递给 ViewModel。 Activity 将实现它并显示Snackbar

    例子:

    但是,可能有一些视图特定的行为无法在 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 中,您可以使用 Data Binding 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

    【讨论】:

    • ViewModel 类不应该包含任何 Android 元素,如用于单元测试的 android.view.View 吗?
    【解决方案2】:

    简短的回答是你没有,这实际上是一件好事。在 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));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-11
      • 1970-01-01
      相关资源
      最近更新 更多