Are actions allowed in MVVM? Android

醉酒当歌 提交于 2019-12-08 02:05:20

问题


If MVVM is all about data binding and cannot do something like view.doThis(), otherwise it's MVP, then how to invoke actions on views?

Suppose I have view that has a snackbar. View is controlled by its ViewModel. How is this ViewModel supposed to show snackbar without going snackbar.show()?


回答1:


In MVVM, ViewModel captures the state of the view. View observes the ViewModel for changes and updates itself. Thus, the communication between View & ViewModel happens through change of values (as against method calls in MVP).

Since Snackbar is like a global behaviour (like Toast), it can be implemented at the Activity/Fragment level. So, you can make a MessageHelper interface and pass it to the ViewModel as a dependency. Activity will implement it and display Snackbar.

Example:

  • ItemViewModel that consumes the interface
  • Activity base class that implements the interface

However, its possible that there is some view specific behaviour which cannot be implemented at the Activity level. For such cases, you can make use of databinding.Observable to trigger an event. For example, lets say we want to animate a particular view. We can create a 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
}

In XML, we can apply this using

    <TextView
        bind:shakeTrigger="@{vm.shakeTrigger}"/>

Then, in the viewModel, you can trigger the shake using Data Binding apis. One way using BaseObservable can be:

public class ConfigurationViewModel extends BaseObservable implements ViewModel {
    @Bindable
    public final Void shakeTrigger = null;

    public void shake() {
        notifyPropertyChanged(BR.shakeTrigger);
    }
}

If you use RxJava, the trigger could be implemented from rx.Observable. You can checkout my library to use RxJava with Data Binding. https://github.com/manas-chaudhari/android-mvvm




回答2:


The short answer is you don't and that's actually a good thing. In MVVM ViewModel is responsible for preparing and storing data for the view. So it gets the data from the model and makes it ready to be set on the view but it doesn't set the value, Setting the value and updating view states are responsibilities of the view itself, View in MVVM watches for changes in data and updates itself.

An example of this would be showing an empty list page when your list is empty. To do this in MVVM, you define a state for the view visibility in your ViewModel lets call it emptyPageVisibility and then update this value appropriately.

public class PlaylistDetailViewModel extends ViewModel {
    private MutableLiveData<Integer> emptyPageVisibility = new MutableLiveData<>();

    private void someMethodInYourViewModel(){
        emptyPageVisibility.setValue(View.VISIBLE);
    }
}

Then inside your view, you observe this and update the view when this data is changed like this

viewModel.getEmptyPageVisibility().observe(this, 
        visibility -> emptyPageView.setVisibility(visibility));


来源:https://stackoverflow.com/questions/39637736/are-actions-allowed-in-mvvm-android

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!