扩展视图如何在MVVM设计模式下工作?

时间:2019-02-11 00:03:44

标签: android mvvm

我正在尝试一边学习Android,一边进行了一些研究,并发现MVVM模式是我要走的路。我对WPF / XAML有所了解。但是,我确实对视图(活动/片段)如何膨胀有疑问。

这是我对设计模式的一般理解:

模型位于底层。该层将具有业务逻辑和实体。对于每个声明的实体,使用Room将一个表存储在SQLite数据库中。为了坚持封装,所有数据成员都是私有的,只能通过get()方法访问。

数据访问层存储我的数据库和实体的DAO。据我了解,DAO是负责在视图模型和数据库之间进行交互的对象。

视图模型是显示数据的方式。由于数据库将在存储库中引用,因此它将与存储库交互以最终访问数据库。

我遇到麻烦的地方是视图模型和视图关系。我了解,视图模型不了解视图,但是视图如何膨胀?我知道这是不正确的-但我的想法是,如果您使用DataBinding将例如onClick属性绑定到ViewModel中的方法,并且假设此方法负责显示Dialog,则ViewModel具有View知识,因为它负责创建对话框。

从本质上讲,我的问题是,在扩大视图时,开发人员如何遵循MVVM范例?如果ViewModel不应该负责与View相关的任何交互,而仅要公开其数据,那么我是否缺少另一层桥梁来弥补通货膨胀?

1 个答案:

答案 0 :(得分:0)

我所做的是将视图呈现逻辑(对话,吐司,小吃店等)抽象化,例如Presenter(不要与MVP Presenter混淆)。然后,交互由ViewModel处理,而实际的 display 由View处理。

例如:

// "Presenter" class, say for a Dialog
public interface DialogPresenter {
    void showDialog();
}

// View Model
public class ViewModel {
    private final DialogPresenter mPresenter;

    public ViewModel(DialogPresenter presenter)  {
        mPresenter = presenter;
    }

    public void onButtonClick() {
        // You can use DataBinding to bind this "onButtonClick()" method to
        // the  button click, then trigger the showing of the dialog. You can
        // add any other non-view related business logic as well. So there is
        // no direct dependencies on Android view classes and this class is
        // unit-testable by mocking out the presenter dependency.
        mPresenter.showDialog();
    }
 }

// Fragment (the "View")
public View onCreateView(...) {
    // View provides an implementation of the abstraction that will actually
    // show the dialog
    mViewModel = FragmentViewModel(new DialogPresenter() {
        public void showDialog() {
            // Show dialog in this fragment
        }
    });
}

这有点绕过,但是可以为您提供视图模型与视图的分离,并使视图模型完全可以进行单元测试。缺点是您需要这个“中间人”,但这通常是在打破依赖关系并使事情更具可测试性时的权衡。

另一种选择是直接在视图中直接连接按钮逻辑:

// Fragment (the "View")
public View onCreateView(...) {
    // Just wire everything up here and test via UI test (Espresso)
    mBinding.button.setOnClickListener(new View.OnClickListener() {
        public void onClick() {
            // Show dialog
        }
    }
}

需要权衡的是,这显然更加直接和直接。您可以使用UI测试相当容易地进行测试。不利的一面是,如果您需要扩展点击行为以添加更多逻辑(验证之类的东西),这将无法扩展。然后,您将开始查看视图中的业务逻辑。

因此,除了最简单的视图之外,我建议所有人都采用第一种方法。

希望有帮助!