在这里插入图片描述

在这里插入图片描述

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 官方设计语言),包含 ScaffoldAppBarTextButton 等常用 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});

  
  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;

  
  State<MyHomePage> createState() => _MyHomePageState();
}

为什么需要 StatefulWidget

因为这个页面包含一个会变化的计数器 _counter,需要在用户点击按钮时更新 UI。

  • final String title;
    接收父组件(MyApp)传入的标题,final 表示不可变。

  • createState()
    返回一个 State 对象(即 _MyHomePageState),状态实际存储在这里

📌 Flutter 中,状态(State)和 UI 描述(Widget)是分离的。Widget 是配置,State 才是数据。


🧠 四、状态逻辑:_MyHomePageState

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  
  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 不知道数据已变。

UI 结构解析:

  • Scaffold:提供标准的 Material 布局结构(AppBar + Body + FAB 等)。
  • AppBar:顶部导航栏,标题来自 widget.title(注意:通过 widget 访问父组件传入的属性)。
  • Center + Column:将两个 Text 垂直居中排列。
  • FloatingActionButton:右下角圆形按钮,点击触发 _incrementCounter

🔍 五、热重载 vs 热重启

代码中的注释特别强调了这一点:

“Notice that the counter didn’t reset back to zero; the application state is not lost during the reload.”

  • 热重载(Hot Reload)
    保留当前状态(如 _counter = 5),只更新 UI 和代码逻辑。适合快速调试样式和逻辑
  • 热重启(Hot Restart,按 R
    重启整个应用,状态重置。用于测试初始化逻辑

✅ 六、总结:这份代码教会了我们什么?

概念 在代码中的体现
Widget 是一切 整个 App 由嵌套的 Widget 构成
声明式 UI build() 方法描述“UI 应该是什么样子”
状态驱动更新 通过 setState() 触发 UI 重建
状态与 UI 分离 StatefulWidget + State 模式
热重载开发体验 修改代码即时生效,不丢失状态

🚀 下一步建议

  1. 动手修改:尝试添加“减一”按钮,或把计数器改成倒计时。
  2. 观察 rebuild:在 build() 方法开头加 print('Rebuilding...'),看看何时被调用。
  3. 探索 DevTools:运行 flutter run --profile 并打开 DevTools,查看 Widget 树和性能分析。

这个小小的计数器 App,是你通往复杂 Flutter 应用的第一步。理解它,你就已经掌握了 Flutter 的灵魂。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐