清理所有的Flutter!

颤动的杂波很难阅读! 要清理!

你知道我不喜欢Flutter吗? 很少 但是,我确实必须习惯于读取较长的垂直参数列表。 在大多数情况下,它们不仅是参数,还是作为参数传递的匿名函数列表,这使它变得更难阅读。 和男人! 有时会有很多混乱! 大量的混乱杂波!

格雷格·佩里的其他故事

当然,可以适应。 它确实有其优点,但我决定对其进行清理。 下面是“之前和之后”的图片。 你怎么看?

原始ContactDetailsPage与新的ContactDetailsPage

举个例子

我以repo。, contacts_service为例。 我随便选了。 我没有选择那些特定的开发人员或任何东西。 碰巧的是,它本身演示了contacts_service插件的用法,但我的版本不是有关“插件”的,而是有关“外观”的。 关于组织的更多信息。 详细了解MVC设计模式。

所以,你喜欢吗? 你看到了什么? 我看干净。 我可以很容易地看到“数据”来自名为Contacts的类中的静态引用。 它特别来自Contact类的“编辑参考”。 毕竟,这是应用程序的编辑屏幕,因此我们可以看到联系人类处于编辑模式! 以下是详细信息。

例如,您可以看到下面的AppBar.title属性正在从Contact的displayName引用中获取其数据。 您知道AppBar的title属性接受一个Widget,因此您可以正确地猜测'Contacts.edit.displayName.text'项目将返回一个Text Widget。 清洁。

ContactDetailsPage.dart

MVC正在发挥作用

在我所有的文章中 ,最受欢迎的最后Flutter + MVC! 至今。 它讨论了如何在Flutter中实现MVC设计模式,您很快就会发现MVC在这里也正在发挥作用。 让我们看一下Contacts类。

Contacts.dart

如果您熟悉我在Flutter中的MVC实现,您将认识到Contacts类是MVC设计中的Controller,因为它扩展了ControllerMVC类。 您还可以看到它实现了一个静态工厂:Joshua Bloch现在著名的2001年原始出版物有效的Java中的第1项。 您会看到它导入了类ContactsService-该应用程序的Model部分。

最后,您可能已经猜到了,此类中引用的所有内容可能都是静态的(与Joshua Bloch的Effective Java 2nd ed。中的第22项保持一致),并且您再一次正确。

Contacts.dart

内外MVC

该应用程序的目录结构也反映了该应用程序开发时采用的MVC方法。 按照设计模式(任何设计模式),将提供有关如何组织逻辑,如何组织代码(甚至组织文件和文件夹)的指南,结构。

例如,保持该结构的一致性和勤奋性,当从一个项目转到另一个项目时,允许开发人员的“翻身”“扎根”。 例如,他们一眼就能看到以下特定项目的“视图”,“控制器”和“模型”的组成部分。

我已采用原始回购协议。 并以这种选择的方式组织起来。 我怀疑甚至不熟悉MVC的开发人员都可以在相当短的时间内理解“万物存在的地方”。 好的设计模式可以做到这一点。

我的“待办事项”列表中有详细介绍此目录结构的后续文章。

该项目的目录结构及其内容

得到它? 得到它了。 好!

现在,回头看看最后一个吸气剂 在课堂上,联系人。 它被称为,编辑,并且引用了一个“库私有”变量,而该变量又引用了实例化的类ContactEdit 。 还记得那个吸气剂吗? 您之前已经看过。 在编辑模式下为联系人! 还有两个类: ContactListContactAdd 。 看看我要去哪里?

您可能已经猜到这里有三件事; 此应用的三种“模式”。 如果您猜到了此应用程序中的三个屏幕,一个屏幕用于添加联系人,一个屏幕用于编辑联系人,一个屏幕用于列出联系人。 再一次,你会是对的。

一个从另一个

让我们从头开始。 让我们看一下ContactAdd类。 但是请注意,您会发现它是从ContactEdit类扩展的。 然后,我们看一下该类,它恰好扩展了ContactList类。 然后我们看一下它,它扩展了另一个名为ContactFields的类。 我们将尽快与他们接触,但是首先,该类有助于在应用程序中“添加”联系人。

类ContactAdd

它加起来。

查看上面的类,您会发现确实是ContactAdd这个类扩展了ContactEdit这个类。 您可以看到这不是一个很大的课程,但是做了很多有趣的事情。 首先,它可以选择在第一个名为init()的方法中引入一个“联系人”对象。 然后,它将值分配给两个属性,称为电话和电子邮件。 由于未在此类中定义它们,因此我们可以假定它们是在其父类或层次结构中另一个继承的类中定义的。 您可以看到init()方法调用了其父级的init()方法,并传入了该Contact对象……如果有的话。

有一个“图书馆私有”变量,分配了一个称为PostalAddress的类。 由getter提供的GlobalKey称为formKey,还有一个名为onPressed的方法。

现在有一些我想念的细节,但是我现在真的希望您看到的是如何在此应用程序的“添加联系人”屏幕中利用此类。

寻找在所有下面的代码的“Contacts.add” 消气 。 我在这里等 (下面有红色的小箭头可以帮助您。毕竟这不是测试。)现在,当您看到下面何时应用它们时,在ContactAdd类中找到的属性和方法将变得有意义。

AddContactPage.dart

它加起来!

“添加联系人”屏幕的表单需要一个“表单密钥”。 好吧,它是从哪里获得该表单密钥的? 回顾一下ContactAdd类 ,您将很容易看到该表单密钥来自何处。 清洁。

调用FlatButton小部件的onPressed方法时(当用户按下屏幕的“保存”按钮时),您要调用哪种方法? 再次回顾一下ContactAdd类 ,我想说的是您将调用其自己的“ onPressed”方法。 这种方法具有“更大的目的”。 您可以看到build()函数实际上指示了控制器要使用的api,不是吗?

我的“待办事项”列表中也有另一篇详细介绍此内容的文章。 那个名单越来越长。

查看添加新联系人时要显示的数据。 您能轻易猜出要输入什么数据吗? 赌你可以! (提示:givedName,middleName,familyName等)。您还可以很容易地看到该数据也将输入到TextFormField小部件列表中。 让我们看下面的原始屏幕 。 看看“数据”和“接口”之间的分隔程度如何?

AddContactPage.dart

现在,向下滚动并再次查看我的版本。

AddContactPage.dart

你怎么看?

编辑联系人

接下来我们要得到什么? 接下来,我们要编辑一个联系人。 我们可以很容易地看到ContactEdit类扩展了ContactList类。 通常如何处理联系人列表中的联系人? 我们通常会添加,编辑和删除联系人,不是。 如果我们改变主意,我们甚至可能“取消删除”联系人。 往下看。 你看到了什么?

类ContactEdit

您可以看到ContactEdit类从类ContactService调用静态方法(应用程序的Modal方面)以添加联系人,删除联系人以及“取消删除”联系人。 您可以看到,传递给这些方法的联系人对象首先被更改为“地图”对象。 您还会看到contact对象参数是可选的,如果为null,则将其分配给“库私有”变量_contact。 注意,该变量来自父类ContactList

联系!

Contact类具有getter toMap 。 如下所示,它还有一个名为Contact.fromMap的命名构造函数。 您可以猜测会发生什么。 您在这里看不到它们,但是该构造函数将地图条目分配给以联系人的字段名称命名的二传手列表。 但是,您确实看到了由这些设置员分配的“库私有”变量的列表。 最后,您将看到getter toMap,它将联系人的属性转换回Map。 您会正确猜到“后端”直接处理Map对象。 清洁。

Contact.dart

列出他们

下一个类是前两个的父类。 它具有一个称为init()的单独方法。 您会看到混乱的“图书馆私有”变量被分配了各种“字段”类。 所有这些变量显然都是从父类ContactFields定义的。 如果没有Contact对象传递给init()方法,则会创建一个“新” Contact对象。 注意,对象已分配给该变量_contact,我们在上一类ContactEdit中看到过。

类ContactList

您的领域是什么?

让我们快速看一下其中一个“字段”类。 上面列出的第一个是类DisplayName。 这个非常类似于其他名称,但是和其他名称一样,它必须是特定的并提供其特定的字段名称displayName。 请注意,变量value来自父类Field。

类DisplayName

注意, 的onSave()是在保存联系人,例如,在被称为AddContactPage的方法下,_formKey.currentState.save()。 当然,可以在主屏幕ContactListPage中找到circleAvatar。

接触领域

该层次结构中的第一个类是我们将要查看的最后一个类ContactFields 。 您已经看到每个班级如何在一个或另一个学位上“建立在上一个班级之上”。 现在,该课程提供什么? 它提供了Field类型的“ field”变量,以及它们相关的gettersetter 。 见下文。

类ContactFields

列出您的联系人

以下是此应用的第一个或“主”屏幕的构建功能。 那些熟悉我的执行在颤振MVC ,知道我考虑了Widget的版本()函数的“主”的应用程序(任何控件的版本()函数实际上)屏幕是在MVC“的视图”实施。 记得?

对于此应用,可通过Controller访问“视图”中显示的所有数据。 因此,在这种情况下,通讯录是此应用程序的控制器。 在下面,只要您看到“联系人”一词,就可以知道其值正在从Controller中提取。 例如,您在这里看不到它,但是'private'变量_contacts从Controller中找到的方法获取其值: Contacts.getContacts()

ContactListPage Build()函数是应用程序的视图

我会保留其原始版本,但是您会迷失在代码中。 如果要进行比较,请查看其原始的Github 。 请注意,我确实在我的版本中放入了Dissmissible小部件(红色箭头),以便轻松删除联系人。 原始版本没有删除联系人的方法,在我的版本中,您可以一目了然地看到显示了哪些字段并通过滑动将其“删除”了!

这个可忽略的地方在哪里?

我在这里可能会领先自己一些,但是那个红色箭头向您介绍了此处应用的一种非常重要的方法:控制器不仅确定“显示”什么,而且还可以对其进行“处理”。 在某种程度上,这种方法使Controller承担了View的工作,并以某种方式(即,以TextFormField,Text和Dismissible的形式)显示数据。

如您在类ContactFields中所看到的,定义了一堆“ Field”类。 在此类Field中,您将在其中找到onDissmissible()方法。

onDissmissible()

吸气剂得到它

上面的方法实际上称为getter ,可忽略。 吸气剂将所需的小部件(在本例中为Dismissible)返回到上面列出的变量newWidget。

被解雇

谈论颤动杂波

正如您在上面看到的,有很多事情要做。 库的设计旨在使开发人员的生活变得更加轻松,但是结果是,它们自身会变得混乱(在后台发生了很多事情。)在这种情况下,与Widget相关的所有参数Dissimissible都是供用户使用...或不提供。 如果不是,则库提供其他值或函数。 这样做允许选择,并且开发人员喜欢选择。

例如,这样做可以使我们在上面的示例中(在红色大箭头旁边)稍微“清理”代码。请注意,该示例有两个匿名函数传递给该函数onDismissible 。 一个用于命名参数child,另一个用于命名参数,已关闭。

我的意思是,这整个过程是为了减少将匿名函数作为参数传递的习惯,还记得吗? 好吧...让我们这样做。 繁荣!

ContactListPage build()函数

每个人都去哪儿了?

上图是与onDismissible方法首先显示的相同build()函数。 它与它的命名参数一起使用:child和dismissed,但是现在它们都消失了! 现在替换为“ Contacts.list.displayName.dissmissible”项。 他们去哪了 猜一下。 如果您猜想它们现在在类DisplayName中 ,可以通过getter displayName访问,那将是正确的。

类DisplayName

首先介绍给您的DisplayName类现在有两个新的实现方法。 父类的每个重写方法Field: onDismissed()onChild() 。 现在,该特定的“逻辑”已嵌入“控制器端”。

MVC意味着可管理性

这导致了“工作分离”。 想象一个开发团队正在开发此应用程序,并为一个开发人员分配了该应用程序的“联系数据”方面。 他甚至都没有访问build()函数的权限! 他在Controller中完成工作,因为Controller负责将数据提供给View(即View可以与Controller对话 )。 因此,他只是向访问“联系数据”所需的“ UI”团队提供API(公共属性和功能)。 没问题。 例如,在这种特殊情况下,他为他们提供了以下信息:“ Contacts.list.displayName.dissmissible”。

做完了

花费了更多的代码,但是您就可以了。 实际上,我更喜欢前一种实现。 这只是一个小小的应用程序,我觉得逻辑分离不必那么明显。 无论如何,关键是您有选择,我们开发人员喜欢选择。 对?

田野班

因此,让我们进一步看一下Field这个类。 您可能已经猜到了。 我创建的这个库使我作为开发人员的生活变得更加轻松。 它使我的代码( build()函数中的代码)更加整洁。 当Controller要提供特定的数据字段时,它可以使用最适合这种情况的Widget来提供。 它可以是TextFormField,Text,ListTile,CheckBox等。 小部件的列表是有限的,但是正在不断增长。 像任何好的库文件一样,它为您完成了很多繁琐的工作。

具有讽刺意味的

看着我。 我开始这篇文章时可能会抱怨在Flutter中找到的参数列表,最后我制作了一个接受77个参数的类库。 而且可能还会有更多! 搞笑!

field.dart

这一切的重点

无论如何,您知道我为什么这样做吗? 在下一个项目中,您将有一个数据库中的数据字段,并将该数据字段显示在TextFormField,ListTile,CircleAvatar中,甚至可能在CheckBox中。 最重要的是将实现Dismissible,以便可以用手指在该行的其他屏幕上滑动来删除数据字段。

关键是,定义一个Field对象,为所有这些Widget传递所有必需的参数,然后完成。 得到它? 现在,您有了一个Field对象,可以将其应用于整个应用程序中的多个屏幕。 你怎么看?

小部件? 多少个小部件?

在撰写本文时,Field类可容纳以下Widget。 同样,可能会添加更多。

TextFormField
文本
富文本
ListTile
CheckBoxListTile
CircleAvatar
可驳回
复选框

那么,这一切的真正意义是什么?

因此,您可以推断Field类仍在进行中。 它位于Utils目录下的文件中,但是您可以看到它并不孤单。 您会看到,Field类仅位于一个更大的存储库中的名为Fields.dart的实用程序文件中。 包含我的下一个软件包版本的mvc_application

大图

在开发过程中,我一直在缓慢但肯定地制作自己的小“应用程序框架 ”,以便在以后的每个项目中使我的生活更轻松。 开发人员当然会这样做-建立他们的工具箱。

随MVC_Pattern一起提供MVC_Application

我对软件包mvc_pattern的发布感到惊讶。 该软件包将具有40年历史的MVC设计模式应用于Flutter应用程序,并且在发布时收到了好评。 我看到了需求,因为这是我大多数应用程序选择的设计模式,很高兴看到许多人仍然欣赏“设计模式的祖父”。

随着时间的流逝,我的工作量越来越大,我的“工具箱”也越来越多。 现在的目的是作为软件包发布我当前的框架mvc_application不是明天,而是很快。 实际上,它只是在mvc_pattern包的顶部工作,但包括我编写并在开发中使用的许多其他库。 其中包括一些我已经公开发布并记录在过去的文章中的内容:

我的终结游戏是什么

那么,这一切的最终目标是什么? 就目前而言,我只是为这个刚刚起步的Flutter社区做出了贡献。 是否使用它。 取走您想要的东西。 诚然,最后,一点点地建立自己的形象并没有什么坏处。 毕竟,这就是我的谋生方式。 那么,未来会有什么呢? 同样,我希望发布软件包mvc_application 。 之后? 哦,我不知道。 mvc_enterprise

干杯。

→Greg Perry的其他故事

有什么问题吗

From: https://hackernoon.com/clean-up-all-the-flutter-69cb308382f4

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值