通过这个简单的 Flutter 示例程序,我们可以快速了解 Flutter 的代码结构,理解每个部分的作用。
dart
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// 这个小部件是你应用程序的根部件。
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// 这是你应用程序的主题。
//
// 尝试这个:尝试用 "flutter run" 运行你的应用程序。你会看到
// 应用程序有一个紫色的工具栏。然后在不退出应用程序的情况下,
// 尝试将下面 colorScheme 的 seedColor 更改为 Colors.green
// 然后调用 "热重载"(保存你的更改或按下 Flutter 支持的 IDE 中的 "热重载" 按钮,或如果你使用命令行启动应用程序,按 "r")。
//
// 注意计数器没有重置为零;应用程序状态在重载期间没有丢失。要重置状态,请改用热重启。
//
// 这也适用于代码,而不仅仅是值:大多数代码更改都可以通过热重载进行测试。
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
// 这个小部件是你应用程序的主页。它是有状态的,意味着
// 它有一个状态对象(在下面定义)包含影响
// 它外观的字段。
// 这个类是状态的配置。它保存由父级(在这种情况下是 App 小部件)提供的值(在这种情况下是标题),并
// 被状态的构建方法使用。Widget 子类中的字段
// 始终标记为 "final"。
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
// 这个对 setState 的调用告诉 Flutter 框架在此状态中
// 发生了变化,这会导致它重新运行下面的构建方法
// 以便显示可以反映更新后的值。如果我们在不调用 setState() 的情况下更改
// _counter,那么构建方法将不会再次被调用,因此看起来不会发生任何事情。
_counter++;
});
}
@override
Widget build(BuildContext context) {
// 每次调用 setState 时都会重新运行这个方法,例如在上面的 _incrementCounter 方法中。
//
// Flutter 框架已经针对快速重新运行构建方法进行了优化,
// 这样你就可以只重建任何需要更新的内容,而无需单独更改
// 小部件的实例。
return Scaffold(
appBar: AppBar(
// 尝试这个:尝试将这里的颜色更改为特定颜色(也许是
// Colors.amber?)然后触发热重载,看看 AppBar
// 在其他颜色保持不变的情况下改变颜色。
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
// 在这里我们从 MyHomePage 对象获取值,该对象是
// 由 App.build 方法创建的,并用它来设置我们的 appbar 标题。
title: Text(widget.title),
),
body: Center(
// Center 是一个布局小部件。它接受一个子项并将其
// 定位在父级的中间。
child: Column(
// Column 也是一个布局小部件。它接受一个子项列表并
// 将它们垂直排列。默认情况下,它的大小适应子项的
// 水平大小,并试图尽可能高于其父级。
//
// Column 有多种属性可控制它如何调整大小以及
// 如何定位其子项。在这里我们使用 mainAxisAlignment 来
// 垂直居中子项;这里的主轴是垂直轴,因为 Column 是垂直的(交叉轴则是
// 水平的)。
//
// 尝试这个:调用 "调试绘制"(在 IDE 中选择 "切换调试绘制"
// 操作,或者在控制台中按 "p"),以查看
// 每个小部件的框架。
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'你按下按钮的次数是:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headlineMedium,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: '增加',
child: const Icon(Icons.add),
), // 这个尾随逗号使得自动格式化在构建方法中更好看。
);
}
}
main()
函数
这是 Flutter 应用程序的入口。与许多编程语言类似,Flutter 程序从 main()
函数开始运行。
runApp()
:将传入的MyApp
组件作为应用的根组件,并将其加载到屏幕上。MyApp
:是一个StatelessWidget
,即无状态的组件。
MyApp
类
dart
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
StatelessWidget
MyApp
继承自 StatelessWidget
,表示它是一个无状态的组件。无状态的组件在创建后不会改变。应用程序的 UI 是基于 Widget
构建的。
MaterialApp
:这是一个 Flutter 提供的预定义 Widget,代表整个应用的根结构。它包含应用的配置,如title
、theme
以及home
。title
:定义应用的标题,通常会显示在应用管理器中。theme
:设置应用的主题,比如颜色、字体等。ThemeData
包含应用的所有视觉属性。home
:指定应用的默认主页,在此示例中是MyHomePage
组件。
MyHomePage
类
dart
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
StatefulWidget
MyHomePage
是一个 StatefulWidget
,它与 StatelessWidget
的不同之处在于它能够管理状态。在这个例子中,我们会点击按钮更新计数器,因此使用 StatefulWidget
。
title
:这是从父组件MyApp
中传递的属性,用于设置主页的标题。final
表示该值在 Widget 构建后不会改变。
_MyHomePageState
类
dart
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text('You have pushed the button this many times:'),
Text('$_counter', style: Theme.of(context).textTheme.headlineMedium),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
状态管理与 setState()
_counter
:这是状态变量,表示按钮点击的次数。_incrementCounter()
:点击按钮时调用此方法,使用setState()
更新状态。setState()
是 Flutter 中用于通知框架更新 UI 的方法。如果不调用setState()
,界面不会重新构建,用户也无法看到按钮点击次数的更新。
Scaffold
Scaffold
是 Flutter 中用于创建标准应用布局的 Widget,提供了 AppBar、Body、FloatingActionButton 等常用 UI 组件的支持。
AppBar
:应用的顶栏(标题栏),显示页面的标题。body
:页面的主体部分,这里使用Center
组件将内容居中显示。Column
:用于将内容垂直排列。这里有两个子组件:一个Text
显示提示信息,另一个Text
显示计数器的当前值。
floatingActionButton
:浮动操作按钮(FAB),用于响应用户的交互行为,点击时调用_incrementCounter()
方法。
代码运行流程概述
- 应用启动 :Flutter 启动后,调用
main()
函数,加载MyApp
组件。 - 构建 UI :
MyApp
返回一个MaterialApp
,该应用的主题和主页(MyHomePage
)被初始化。 - 显示页面 :
MyHomePage
调用其对应的State
类_MyHomePageState
,该类定义了计数器、构建方法,以及当按钮被按下时的响应逻辑。 - 状态更新 :每次点击按钮时,
_incrementCounter()
方法更新计数器,并通过setState()
触发界面重绘,更新显示的计数值。
代码中涉及的核心 Widgets:
StatelessWidget
和StatefulWidget
:分别用于构建无状态和有状态的组件。MaterialApp
:定义应用的根结构,配置主题等属性。Scaffold
:提供标准应用布局结构。AppBar
:应用的标题栏。Column
:垂直排列子组件。FloatingActionButton
:用于处理用户点击的操作按钮。setState()
:用于更新组件的状态,并触发界面重绘。
总结
通过这个简单的计数器示例,我们可以清晰地理解 Flutter 应用的基本结构:main()
函数初始化应用,MaterialApp
设置应用的主题和主页,StatelessWidget
用于构建无状态的 UI 组件,StatefulWidget
用于管理和更新状态。Flutter 的状态管理机制让 UI 更新变得非常简洁高效。