by QuickBird Studios

通过QuickBird Studios

使用Model-View-ViewModel使用Dart Streams使Flutter中的代码更清晰 (Use Model-View-ViewModel to make your code cleaner in Flutter with Dart Streams)

A common problem when developing apps is that you end up with over-complicated classes. These classes contain view logic as well as business logic. Both are so intertwined that it’s impossible to test them independently. Code-readability suffers, and future code changes are hard to implement.

开发应用程序时的一个常见问题是您最终遇到了过于复杂的类。 这些类包含视图逻辑和业务逻辑。 两者是如此交织在一起,以至于无法独立测试它们。 代码可读性受到影响,将来的代码更改很难实现。

Since there are almost no constraints on your architecture in Flutter, it’s fairly easy to run into this problem. Some developers write all their code in the Widget until they realize the mess they produced. Reusing code in other projects seems impossible, and in the end, you write most of your code twice. Model-View-ViewModel (MVVM) tries to solve that by splitting up business logic and view details.

由于在Flutter中,您的体系结构几乎没有任何限制,因此遇到此问题相当容易。 一些开发人员在Widget中编写所有代码,直到他们意识到产生的混乱。 在其他项目中重用代码似乎是不可能的,最后,您将大部分代码编写了两次。 Model-View-ViewModel(MVVM)试图通过拆分业务逻辑和查看详细信息来解决此问题。

In this article, we show you how MVVM with Flutter could look like. We’ll create a functional reactive ViewModel using Dart’s Stream API.

在本文中,我们向您展示带有Flutter的MVVM的外观。 我们将使用Dart的Stream API创建功能性的React式ViewModel。

模型-视图-视图模型 (Model-View-ViewModel)

Before we look at any code, we should get a basic understanding of MVVM. If you’re familiar with MVVM, you can skip this part.

在看任何代码之前,我们应该对MVVM有基本的了解。 如果您熟悉MVVM,则可以跳过此部分。

The main goal behind MVVM is to move as much of the state and logic from the View into a separate entity. This name given to this entity is the ViewModel. The ViewModel also contains the business logic. It serves as the mediator between the View and the Model.

MVVM的主要目标是将视图中尽可能多的状态和逻辑转移到一个单独的实体中。 赋予该实体的名称是ViewModel。 ViewModel还包含业务逻辑。 它充当视图和模型之间的中介。

The ViewModel has basically two responsibilities:

ViewModel基本上有两个职责:

  • it reacts to user inputs (e.g. by changing the model, initiating network requests, or routing to different screens)它对用户输入做出React(例如,通过更改模型,发起网络请求或路由到不同的屏幕)
  • it offers output data that the View can subscribe to它提供View可以订阅的输出数据

The View does not contain any business logic. These are the responsibilities of the view:

视图不包含任何业务逻辑。 这些是视图的职责:

  • it reacts to new output states of the ViewModel and renders them accordingly (e.g. by showing a String in a text field)它对ViewModel的新输出状态做出React并相应地渲染它们(例如,通过在文本字段中显示String)
  • it tells the ViewModel about new user inputs (e.g. button-clicks, text-changes, screen touches)它告知ViewModel新的用户输入(例如,按钮单击,文本更改,屏幕触摸)

In contrast to popular MVC approaches, the Fragment / Activity / UIViewController or Widget does not contain business logic in MVVM. It is a humble view that renders the ViewModel’s output states. The ViewModel does not know the View (a difference from forms of MVP and MVC). It offers output states that the View observes:

与流行的MVC方法相反,Fragment / Activity / UIViewController或Widget在MVVM中不包含业务逻辑。 这是一个简陋的视图,呈现ViewModel的输出状态。 ViewModel不知道视图(与MVP和MVC的形式有所不同)。 它提供视图观察到的输出状态:

Flutter中的MVVM (MVVM in Flutter)

In Flutter, the Widget represents the View of MVVM. The business logic sits in a separate ViewModel-class. The ViewModel is totally platform-independent. It contains no dependencies to Flutter, and can be easily reused, for example in a web project.

在Flutter中,小部件表示MVVM的视图。 业务逻辑位于单独的ViewModel类中。 ViewModel完全独立于平台。 它不包含对Flutter的依赖关系,并且可以轻松地重用,例如在Web项目中。

That is one of MVVM’s biggest powers. We can create a Mobile App and a website that both share the same ViewModel. You don’t need to reinvent and write the logic twice.

这是MVVM的最大功能之一。 我们可以创建共享相同ViewModel的移动应用程序和网站。 您无需重新发明并编写逻辑两次。

示例:电子邮件订阅小部件 (Example: Email Subscription Widget)

Let’s look at an example. We’ll implement a Newsletter signup-form with an email textfield and a submit button. The button is disabled and the user sees an error if the email is invalid:

让我们来看一个例子。 我们将实现带有电子邮件文本字段和提交按钮的新闻简报注册表单。 如果电子邮件无效,该按钮将被禁用,并且用户会看到错误消息:

丑陋的方式 (The ugly way)

Without any specific architecture, the business logic and the current state are part of the widget. It could look something like this:

没有任何特定的体系结构,业务逻辑和当前状态就是小部件的一部分。 它可能看起来像这样:

The problem is that view logic, view state, and business logic are mixed up. That leads to a few problems:

问题是视图逻辑,视图状态和业务逻辑混合在一起。 这会导致一些问题:

  1. It’s hard to unit test很难进行单元测试
  2. Other Dart projects cannot reuse the business logic, since it’s intertwined with Flutter-dependent View logic其他Dart项目无法重用业务逻辑,因为它与依赖Flutter的View逻辑交织在一起
  3. This style gets messy very soon and you end up with huge Widget classes这种样式很快就会变得凌乱,您最终会得到大量的Widget类

Let’s see how we can improve this…

让我们看看如何改善这一点……

MVVM解决方案 (Solution with MVVM)

As explained above, the ViewModel has Input and Output parameters. We will add an ‘input’ or ‘output’ prefix for the sake of clarity.

如上所述,ViewModel具有输入和输出参数。 为了清楚起见,我们将添加“ input ”或“ output ”前缀。

All Inputs are Sinks. The View can use those to insert data into the ViewModel. All Outputs are Streams. The View can listen for changes by subscribing to the Streams. The interface for our ViewModel looks like this:

所有输入均为Sinks 。 视图可以使用这些视图将数据插入到视图模型中。 所有输出均为Streams 。 View可以通过订阅Streams来侦听更改。 我们的ViewModel的界面如下所示:

We are using a StreamController as an input Sink. This StreamControllerprovides a stream that we can use internally to handle those input events.

我们使用StreamController作为输入Sink 。 这个StreamController提供了一个流,我们可以在内部使用它来处理那些输入事件。

将视图绑定到ViewModel (Binding a View to the ViewModel)

So how do we supply inputs and handle output events? To supply input values to the ViewModel, we insert them into the ViewModel’s Sinks. We’ll bind a Widget to the ViewModel. In this case, we insert the TextField’s text whenever it changes.

那么,我们如何提供输入并处理输出事件呢? 为了向ViewModel提供输入值,我们将它们插入到ViewModel的Sinks 。 我们将小部件绑定到ViewModel。 在这种情况下,只要文本字段发生更改,我们就将其插入。

You listen to the ViewModel Outputs by subscribing to the Output-Streams.

您可以通过订阅的输出- 倾听视图模型输出。

Flutter provides a really cool Widget called StreamBuilder that will update whenever a Stream provides a new value. We won’t call setState ever again!The StreamBuilder’s builder method gives you a snapshot whenever it builds. This snapshot contains information about the stream, its data, and its errors. If our stream did not emit any value, snapshot.data will be null. So, be careful.

Flutter提供了一个非常酷的小部件,称为StreamBuilder ,它将在Stream时更新 提供新的价值。 我们不会再调用setStateStreamBuilder的 builder方法会在builder为您提供快照。 该快照包含有关流,其数据及其错误的信息。 如果我们的流没有发出任何值,则snapshot.data将为null。 所以要小心

QUICK TIP: Try to help the Dart compiler when working with streams. Add all the needed generic types to avoid runtime errors.

快速提示:在使用流时,请尝试帮助Dart编译器。 添加所有必需的通用类型,以避免运行时错误。

Here you can see the whole picture:

在这里您可以看到整个图片:

As you can see, the View’s only responsibility is rendering Outputs and supplying Inputs to the ViewModel. Our Widget is therefore super slim and easy-to-read.

如您所见,View的唯一职责是呈现输出并将输入提供给ViewModel。 因此,我们的小部件超薄且易于阅读。

结论 (Conclusion)

We started out with MVVM in the native world and wondered if it would also work with Flutter. After trying it out, we can say: MVVM is a great fit for Flutter as well.

我们从原生的MVVM开始,想知道它是否也可以与Flutter一起使用。 在尝试之后,我们可以说:MVVM也非常适合Flutter。

We love how nicely the View-logic is separated from the business logic. We love how easy ViewModels can be unit-tested. And we love how Dart ViewModels can be shared with other platforms that are using Dart.

我们喜欢将视图逻辑与业务逻辑很好地分离。 我们喜欢ViewModels可以轻松进行单元测试。 我们喜欢Dart ViewModels如何与使用Dart的其他平台共享。

The Stream-API takes some time to get used to, but afterward it feels very smooth. For more complicated tasks we used RxDart. This adds functionality to the standard Stream-API.

Stream-API需要一些时间来习惯,但是之后感觉很流畅。 对于更复杂的任务,我们使用了RxDart。 这将功能添加到标准Stream-API。

If you’re just hacking a small app, then the normal “put-everything-in-one-class” approach might be more straightforward. If you plan to build a bigger app, though, MVVM might be the architecture for you.

如果您只是在破解一个小型应用程序,那么通常的“一劳永逸”的方法可能会更简单。 但是,如果您打算构建更大的应用程序,那么MVVM可能是适合您的体系结构。

Originally published at quickbirdstudios.com on June 12, 2018.

最初于2018年6月12日发布在quickbirdstudios.com上。

翻译自: https://www.freecodecamp.org/news/app-architecture-mvvm-in-flutter-using-dart-streams-26f6bd6ae4b6/

使用Model-View-ViewModel使用Dart Streams使Flutter中的代码更清晰相关推荐

  1. vsCode使vue中的代码高亮

    打开vsCode,找到左侧导航栏点击**[1]的位置,在[2]处输入Vetur**,然后点击**[3]**等待加载即可.

  2. Model/View 教程

     说明:这篇博客基本都是翻译于Qt官方的Model/View Tutorial教程,无法理解的地方建议转到原文,同时,由于译者水平有限,如有差错欢迎指出. 原文:http://qt-project ...

  3. 使用ASP.NET实现Model View Presenter(MVP)

    作者:Billy McCafferty 翻译:张善友<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office: ...

  4. Qt学习笔记-----Model/View架构之自定义Model

    Model/View Framework中提供了模型model的抽象基类QAbstractItemModel, 如果需要自定义模型就需要继承这个类并且实现一些必要的函数. 此外,Qt中又提供了QAbs ...

  5. QT Basic 014 Model/View programming (模型、视图编程)

    前言:本文不是纯文本翻译,加入了对概念的理解,纯文本翻译,请看文后的一个链接. Model/View Programming Introduction to Model/View Programmin ...

  6. (一) Qt Model/View 的简单说明

    目录: (一) Qt Model/View 的简单说明 .预定义模型 (二)使用预定义模型 QstringListModel例子 (三)使用预定义模型QDirModel的例子 (四)Qt实现自定义模型 ...

  7. 用C#实现MVC(Model View Control)模式介绍

    用C#实现MVC(Model View Control)模式介绍 作者:Matthew Cochran December 12, 2005 原文地址:http://www.c-sharpcorner. ...

  8. 初探 MVP(Model View Presenter) 设计模式

    刚刚转入C#开发不久,发现了一个类似于Java里的MVC模式的东东--MVP(Model View Presenter) 模式,个人感觉MVP模式真的和MVC差不多,MVC我这里就不解释了,着重讲讲M ...

  9. Qt中model/view设计模式

    Qt Model/View 学习笔记 (一) Qt 4推出了一组新的item view类,它们使用model/view结构来管理数据与表示层的关系.这种结构带来的 功能上的分离给了开发人员更大的弹性来 ...

最新文章

  1. Bash : test 命令
  2. mk_trustonic.mk编译脚本
  3. 【大数据】企业级大数据技术体系概述
  4. boost::mp11::mp_max相关用法的测试程序
  5. Yii重写ActiveForm
  6. React Antd Upload自定义上传customRequest
  7. .net core 生成二维码
  8. mybatis中经典的9种设计模式
  9. java求职面试_Java面试求职
  10. 微课|中学生可以这样学Python(8.3节):递推算法例题讲解
  11. OsharpNS轻量级.net core快速开发框架简明入门教程-基于Osharp实现自己的业务功能...
  12. debian vbox设置_在Debian 9 Stretch系统上安装VirtualBox的两种方法
  13. 软件开发生命周期及各阶段文档
  14. Tool:Adobe Photoshop
  15. html 显示 16进制 颜色,16进制颜色(html颜色值)
  16. 微信小程序打开外部链接
  17. 自学mysql教程 资料_数据库MYSQL,自学,命令,教程。
  18. 打造3大产品差异化,成就下一个亚马逊爆品!
  19. linux 下的字体引擎
  20. 计算机工作原理与系统组成?,计算机工作原理及系统组成

热门文章

  1. 入门级控件 c# 1615014955
  2. dj鲜生-27-登陆装饰器-使用django内置的登陆装饰器
  3. python-虚拟环境的创建与使用-针对linu系统
  4. python-计算机二级考试-报考笔记
  5. 配置远程服务器的别名
  6. 零基础:邪恶带你3步快速掌握iSCSI搭建
  7. .NET中Redis安装部署及使用方法简介附-开源Redis操作辅助类
  8. 用electron写桌面应用
  9. 7、C语言 —— 字符串常用处理函数
  10. JavaScript 设计模式核⼼原理与应⽤实践 之 创建型:工厂模式·简单工厂——区分“变与不变”