// 用 Dart 编写的代码从主函数开始执行,runApp 是 Flutter 的一部分,而且需要组件作为我们 app
// 的容器。在 Flutter 中,
// 万物皆组件。
void main() => runApp(new TodoApp());
// Flutter 中,万物皆组件,甚至是整个 App 本身
class TodoApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: ‘Todo List’,
home: new Scaffold(
appBar: new AppBar(
title: new Text(‘Todo List’)
)
),
);
}
}
组件
这一小段代码显示了 Flutter 中一个重要的概念 —— 万物皆组件。我们的整个应用程序是一个组件,其中包含 MaterialApp
组件。Scaffold
是一个组件,它可以帮助我们快速创建合适的 Material 布局,而不用担心手动设置样式。AppBar
是一个接受标题的组件,它会在屏幕顶部创建一个栏,这在应用程序中很常见。在 Android 上,它会将文本左侧对齐,而在 iOS 上,它会将文本居中。
由于我们对应用程序进行了比较大的改动,所以这次热重载将无法正常工作。这次我们需要完全重启应用程序。在命令行中,输入 R
—— 注意它是大写的,与热重载不同。你将看到一个带标题栏的简单应用程序。
Android(Pixel 2)与 iOS(iPhone X)上标题栏样式的区别
Stateless Widgets 和 Stateful Widgets
为了使我们的应用看起来更像一个待办事项应用程序,我们应当展示一些任务。你可能已经注意到我们上面的简单应用程序是一个 StatelessWidget
。这意味着无法动态修改。对于我们的待办事项应用程序来说,这并不好,因为待办事项会一直添加和删除。但是,StatelessWidget
可以生成动态的子项,它们是StatefulWidget
。让我们从整个 app 容器开始分析我们的有状态功能(待办事项列表容器)。
要创建一个 stateful widget,我们需要两个类 —— 一个用于组件本身,另一个用于创建状态。这个设置允使我们可以轻松保存状态,并能够使用热重载等功能。
为什么一个 stateful widget 需要两个类? 想象一下,我们有一个待办事项列表组件,里面有五个待办事项。当我们往列表中添加另一个事项时,Flutter 会以不同的方式更新屏幕。你可能希望它只是将这一项添加到现有组件中。实际上,它创建了一个全新的组件,并把它同旧的组件进行比较,以确定在屏幕上进行哪些更改。
由于我们在每次更改时都会创建一个新窗口组件,所以我们无法在窗口组件中存储任何状态,因为它会在下一次更改时丢失。这就是为什么我们需要一个单独的 State 类。
下面的代码显示了我们新的有状态应用。它在功能上与我们之前的代码相同,但现在可以轻松更改待办事项列表的内容了。用下面的代码替换 lib/main.dart