Flutter之旅
上QQ阅读APP看书,第一时间看更新

1.4.1 命令式UI编程与声明式UI编程

很多人都觉得Flutter和Android或iOS的代码编写风格不一样,但具体哪里不一样也说不清。我们先看一下源码中对Widget的描述:“Widget是对Element配置信息的一种描述。”它是Flutter框架的中心层次,一个Widget是用户界面上不可改变的描述。Widget可以被加载成Element,这些Element管理着底层的渲染树。

Widget本身没有可变的状态,因为它所有的字段都要标记成final,表示无法再被修改。如果希望一个Widget拥有状态,可以使用StatefulWidget,它将State对象加载为Element,并合并到树中时,通过StatefulWidget.createstate方法来创建State对象。

现在来思考一下Flutter界面规则和Android或iOS有什么不同。从面向对象编程以来,桌面程序都是采用命令式UI编程,而Android和iOS等“后辈”取其精华,借鉴发扬。

命令式UI编程是什么?拿Android来说,界面上的构成元都是一个个实际对象,并且这些对象本身已经封装了一套属于它的UI表现。改变界面展现效果等价于设置UI对象的属性,然后框架重新刷新界面。操作与交互则是调用对象的方法和设置回调函数。

通过简单的表达式描述:命令式UI编程中界面与交互通过操作View对象自身实现。

但在Flutter中,有一个非常重要的特性:Widget的所有字段都是final类型。这就说明你不能像进行命令式UI编程那样去直接修改界面信息,比如在setState内使用下面的语句会报错。


widget.title="当前数字:${_counter}";

按照曾经的思维:Widget代表界面实体对象,设置对象的属性不是天经地义吗?所以我们的思维要从命令式UI编程中跳出来。Widget并不代表界面实体对象,只是界面实体对象的一个配置的描述,认清这个问题是学习Flutter的第一步。

一个Widget在某一时刻映射出一个界面,如果将界面的所有表现效果看作状态,初始项目中通过自加方法改变_counter属性来使界面状态发生变化,重建出新的Widget来映射新的界面,从而实现界面变化。这就是声明式UI编程,通过界面配置信息去映射界面。

声明式UI编程更像是函数,状态State作为自变量,通过映射关系形成界面(因变量)。

StatelessWidget用于在给定配置和环境的状态下始终以相同方式构建Widget。这表示无论何时,自变量只会映射出唯一的因变量,即UI=f(State)。