Hello Widget

2,392 阅读5分钟

欢迎点赞,转载请注明出处

这一章,你需要对照Flutter官方文档编写第一个 Flutter 应用,完成一个稍微复杂一些的初级项目,我们姑且叫它Hello Widget。该项目功能是:为一个创业公司生成建议的公司名称。用户可以选择和取消选择的名称、保存喜欢的名称。该代码一次生成十个名称,当用户滚动时,会生成一新批名称。
官方示例步骤已经非常清楚了,本文这里对官方示例代码一些细节进行补充,方便大家进一步理解,系统地学习还需要阅读后续的章节。

创建一个StatelessWidget

  • 第5行 package表明依赖于项目外部库,比如此处是依赖于我们之前已经安装过的Flutter SDK。除了package:之外还可能是其他库包,如核心库dart:。
  • 第7行 语法 => 表达式 是 { return 表达式; } 的简写, => 有时也称之为胖箭头语法。所以此处改为以下代码形式也是等价的:
void main(){
    return runApp(MyApp());
}
  • 第16行等价于title: new Text('Welcome to Flutter'),Dart2的构造函数new关键字可以省略。
  • Widget描述了它们的视图在给定其当前配置和状态时应该看起来像什么。当widget的状态发生变化时,widget会重新构建UI,Flutter会对比前后变化的不同, 以确定底层渲染树从一个状态转换到下一个状态所需的最小更改。

  • pubspec.yaml文件是用YAML语法编写的配置文件,人机可读性强。YAML官方描述:YAML is a human friendly data serialization standard for all programming languages。
  • 第26行 ^表示的一种Caret语法版本约束管理,^3.1.0表示english_words的>=3.1.0且<4.0.0的版本都是功能兼容的;具体写哪个版本号,我们可以在pub.dev上查看,如下图:

可以看到english_words最新版本是3.1.5,所以我们可以将第26行改为 english_words:^3.1.5,也是等价的。实际上,我们可以看到即使不修改成3.1.5,生成的pubspec.lock文件下生成的english_words也是在Caret语法约束下的3.1.5最新版本。如下图:

  • 第13行 final关键字表示变量的值只能被设置一次。
  • WordPair类的使用方法可以从english_words包的官方地址找到。
  • 尽管Dart是强类型语言,但是在声明变量时指定类型是可选的,因为Dart可以进行类型推断。所以第13行的等价写法为:final WordPair wordPair=WordPair.random()
  • 第19行 // Appbar 注释是Android Studio默认自动生成的,方便括号作用域阅读。如果你不喜欢这个效果的话,可以在设置里关闭它。

试一试

查看WordPair用法,我们把示例中的UpperCamelCase改成lowerCamleCase形式的,即首字母小写,后续单词首字母大写的形式,如shuZiMeiTi。

创建一个StatefulWidget

  • 第20行 RandWords构造函数内部会立即调用第37行createState函数。
  • 第37行 RandomWOrdsState()内部会调用第29行build函数。
  • 第27行 State<RadomWords>改为State<StatefulWidget>,你会发现运行效果是一样的,目前的功能还比较简单,泛型类型作用还没有体现。
  • 通过这些代码片段,你可以发现,类的命名都是名词性的,采用PascalCase命名规则,变量命名都是名词性的,采用camleCase命名规则,方法命名都是动词性,采用calmeCase命名规则。

  • 第21行 <WordPair>[]等价于new List<WordPair>(),可以理解为生成一个元素类型为WordPair的集合。
  • 第22行 final和const都可以表示常量;一个 const 变量是一个编译时常量(const 变量同时也是 final 的)。一个类的实例变量可以是 final 的但不可以是 const 的, final 实例变量必须在构造器开始前被初始化。const 关键字不仅仅可以用来定义常量,还可以用来创建 常量值,该常量值可以赋予给任何变量。也可以将构造函数声明为 const 的,这种类型的构造函数创建的对象是不可改变的,如此处const TextStyle
  • 第22行 fontSize: 18.0为初始化TextStyle构造函数指定的入参赋值的写法形式。
  • 第36行 EdgeInsets.all(16.0)表示ListView上下左右四个方向的内边距都是16。
  • 第42行 generateWordPairs()函数是来自于english_words库里的函数。考虑可读性和可维护性,可以为引入的库起一个别名,如Words,这样就可以写成Words.generateWordPairs()的形式, 也方便代码智能提示功能。修改之处,如下图红框所示:

试一试

在前面示例代码的基础,完整的main.dart戳这里,尝试进行修改实现以下效果,即文本变为红色,下图为iPhone 11 Pro Max模拟器:

提示:选中TextStyle,右键弹出菜单,然后选择Declaration,看看可以发现什么:

创建一个新页面跳转

参考这里的说明,完整的main.dart戳这里,我们可以先大致了解基本逻辑脉络即可。

  • 第68行Icons是Flutter Widget内置对象,内置的图标集看这里
  • 第72行setState的作用是告诉框架去重绘ListView Widget,也就是会再次调用到第59行_buildRow函数。

  • 第87行 Iterable<ListTile>表示按顺序访问的ListTile元素的集合。Iterable可迭代对象的元素通过Iterator来访问,该迭代器使用iterator的getter方法来获取, 并且可使用迭代器对所有值进行单步遍历。
  • 这段代码的意思是遍历_saved对象每一个元素pair,生成一个可迭代对象ListTile。等价的代码类似下面的写法:
          final Set<ListTile> tiles=new Set<ListTile>();
          for (int i=0;i<_saved.length;i++){
            ListTile lt=new ListTile(
              title: new Text(
                _saved.elementAt(i).asPascalCase,
                style: _biggerFont,
              ),
            );
            tiles.add(lt);
          }

实验二

在本节代码的基础上,尝试实现下图的演示效果。返回上一个页面可以使用Navigator.of(context).pop()

CDk5fJLmd6YZ9p2

上一篇 Hello World 下一篇 Hello Dart