

main() 到计数器 App当你运行 flutter create 命令创建新项目时,Flutter 会自动生成一个经典的“计数器”示例应用。这段代码看似简单,却浓缩了 Flutter 开发的核心概念:入口函数、Widget 树、状态管理、热重载机制等。
本文将带你逐行解读这份默认代码,帮助你真正理解每一部分的作用,为后续深入学习打下坚实基础。
main() 与 runApp()import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}import 'package:flutter/material.dart';
引入 Flutter 的 Material Design 组件库(Google 官方设计语言),包含 Scaffold、AppBar、TextButton 等常用 Widget。
void main()
Dart 程序的入口函数,就像 C 或 Java 中的 main。
runApp(const MyApp());
将 MyApp 这个 Widget 作为根节点挂载到屏幕上。
💡 所有 Flutter 应用都是由 Widget 构成的树形结构,runApp() 启动这棵树的渲染。
MyApp(无状态 Widget)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
表示这个组件没有内部状态——一旦创建,UI 不会随数据变化而自动更新(适合静态内容)。
build() 方法
每次需要渲染 UI 时都会调用此方法,返回一个 Widget 树。在这里,我们返回了 MaterialApp。
MaterialApp
是整个应用的“容器”,提供:
theme)home 指定首页)ColorScheme.fromSeed(seedColor: Colors.deepPurple)
使用 Material 3 的配色系统,以 deepPurple 为种子色自动生成一套协调的主题色。
✅ 小实验:把
deepPurple改成Colors.green,保存后触发热重载(Hot Reload),你会发现整个 App 的主题色立刻变了,但计数器数字没重置——这就是热重载的魔力!
MyHomePage(有状态 Widget)class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}StatefulWidget?因为这个页面包含一个会变化的计数器 _counter,需要在用户点击按钮时更新 UI。
final String title;
接收父组件(MyApp)传入的标题,final 表示不可变。
createState()
返回一个 State 对象(即 _MyHomePageState),状态实际存储在这里。
📌 Flutter 中,状态(State)和 UI 描述(Widget)是分离的。Widget 是配置,State 才是数据。
_MyHomePageStateclass _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
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,
child: const Icon(Icons.add),
),
);
}
}setState()_counter 是状态变量,初始值为 0。FloatingActionButton),会调用 _incrementCounter()。setState() 是关键!
它告诉 Flutter:“我的状态变了,请重新调用 build() 方法刷新 UI。”⚠️ 如果你直接写
_counter++而不调用setState(),UI 不会更新!因为 Flutter 不知道数据已变。
Scaffold:提供标准的 Material 布局结构(AppBar + Body + FAB 等)。AppBar:顶部导航栏,标题来自 widget.title(注意:通过 widget 访问父组件传入的属性)。Center + Column:将两个 Text 垂直居中排列。FloatingActionButton:右下角圆形按钮,点击触发 _incrementCounter。代码中的注释特别强调了这一点:
“Notice that the counter didn’t reset back to zero; the application state is not lost during the reload.”
_counter = 5),只更新 UI 和代码逻辑。适合快速调试样式和逻辑。R):
重启整个应用,状态重置。用于测试初始化逻辑。概念 | 在代码中的体现 |
|---|---|
Widget 是一切 | 整个 App 由嵌套的 Widget 构成 |
声明式 UI | build() 方法描述“UI 应该是什么样子” |
状态驱动更新 | 通过 setState() 触发 UI 重建 |
状态与 UI 分离 | StatefulWidget + State 模式 |
热重载开发体验 | 修改代码即时生效,不丢失状态 |
build() 方法开头加 print('Rebuilding...'),看看何时被调用。flutter run --profile 并打开 DevTools,查看 Widget 树和性能分析。这个小小的计数器 App,是你通往复杂 Flutter 应用的第一步。理解它,你就已经掌握了 Flutter 的灵魂。