在本节课中,我们将从零开始创建并运行第一个 Flutter 应用,深入理解项目结构,并解析 Flutter 应用的启动原理。通过本节课的学习,你将掌握 Flutter 开发的基本工作流程。
一、使用 flutter create
命令创建项目
Flutter 提供了便捷的命令行工具来快速生成标准化的项目结构。
步骤 1:打开终端 / 命令提示符
- Windows:使用
Win + R
输入cmd
打开命令提示符,或使用 PowerShell - macOS/Linux:使用
Spotlight
搜索Terminal
或通过应用程序文件夹打开终端
步骤 2:创建项目
在终端中输入以下命令:
bash
flutter create my_first_app
flutter create
是创建新项目的命令my_first_app
是你的项目名称(请使用小写字母,单词之间用下划线连接)
执行命令后,Flutter 会自动创建一个完整的项目结构,包括 iOS 和 Android 平台的配置文件。创建过程可能需要几分钟时间,取决于你的网络速度(需要下载必要的依赖包)。
步骤 3:进入项目目录
创建完成后,使用 cd
命令进入项目文件夹:
bash
cd my_first_app
二、运行第一个应用(模拟器 / 真机)
创建好项目后,我们可以在模拟器或真机上运行这个默认的 Flutter 应用。
准备工作
-
确保你已经安装并配置好了 Flutter 开发环境(可通过
flutter doctor
命令检查) -
准备好运行设备:
-
模拟器:
- Android:通过 Android Studio 启动 Android 模拟器
- iOS(仅 macOS):通过 Xcode 启动 iOS 模拟器
-
真机:
- Android:开启 USB 调试模式,用 USB 连接电脑
- iOS(仅 macOS):通过 USB 连接 iPhone,需要在 Xcode 中配置开发者账号
-
运行应用
在项目目录下,执行以下命令:
bash
flutter run
Flutter 会自动检测可用设备并安装应用。首次运行可能需要较长时间,因为需要编译原生代码和下载依赖。
运行成功后,你将在设备上看到一个默认的计数器应用,包含一个显示数字的文本和一个可以点击的按钮。
常用运行命令
r
:热重载(Hot Reload)- 快速应用代码更改,保留应用状态R
:热重启(Hot Restart)- 重新启动应用,清除应用状态p
:显示网格辅助线q
:退出运行模式
三、项目目录结构解析
让我们来了解一下 Flutter 项目的目录结构及其作用:
plaintext
my_first_app/
├── .dart_tool/ # Dart 工具链生成的文件
├── .idea/ # Android Studio 配置文件(Windows/macOS)
├── android/ # Android 平台相关代码和配置
├── build/ # 编译生成的文件
├── ios/ # iOS 平台相关代码和配置
├── lib/ # Dart 源代码(核心目录)
│ └── main.dart # 应用入口文件
├── linux/ # Linux 平台相关代码(可选)
├── macos/ # macOS 平台相关代码(可选)
├── test/ # 测试代码目录
├── web/ # Web 平台相关代码(可选)
├── windows/ # Windows 平台相关代码(可选)
├── .gitignore # Git 忽略文件配置
├── .metadata # Flutter 项目元数据
├── analysis_options.yaml # Dart 代码分析配置
├── pubspec.lock # 依赖包版本锁定文件
├── pubspec.yaml # 项目依赖和配置文件
├── README.md # 项目说明文档
核心目录和文件详解
-
lib 目录
- 这是我们开发的主要目录,所有 Dart 源代码都存放在这里
main.dart
是应用的入口文件,包含main()
函数- 随着项目增大,我们会创建更多 Dart 文件和子目录来组织代码
-
pubspec.yaml
- 项目的配置文件,类似于前端的
package.json
或后端的pom.xml
- 包含项目名称、描述、版本等基本信息
dependencies
部分用于声明项目依赖的包flutter
部分可配置资源文件(图片、字体等)- 修改后需要运行
flutter pub get
命令来更新依赖
- 项目的配置文件,类似于前端的
-
android 目录
- 包含 Android 平台的原生代码和配置
- 当需要进行 Android 平台特定的配置或开发时使用
- 包含 AndroidManifest.xml、Gradle 配置等
-
ios 目录
- 包含 iOS 平台的原生代码和配置
- 当需要进行 iOS 平台特定的配置或开发时使用
- 包含 Info.plist、Podfile 等配置文件
-
test 目录
- 用于存放测试代码
- 支持单元测试、Widget 测试和集成测试
四、入口函数 main()
与 runApp()
原理
让我们打开 lib/main.dart
文件,分析 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(primarySwatch: Colors.blue),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
// ... 省略部分代码
main()
函数
main()
函数是 Dart 程序的入口点,所有 Dart 应用都从main()
函数开始执行- 在 Flutter 中,
main()
函数的主要作用是启动应用
dart
void main() {
runApp(const MyApp());
}
runApp()
函数
runApp()
是 Flutter 框架提供的核心函数,定义在package:flutter/material.dart
中- 它的作用是将给定的 Widget 作为应用的根 Widget,并将其附加到屏幕上
runApp()
会创建一个 Flutter 引擎实例,初始化应用,并开始渲染流程- 它接收一个 Widget 参数,这个 Widget 将成为整个应用 Widget 树的根节点
应用启动流程
- 执行
main()
函数,这是 Dart 程序的起点 - 在
main()
函数中调用runApp()
函数,并传入根 Widget(示例中是MyApp
) - Flutter 引擎初始化,准备渲染环境
- 从根 Widget 开始,构建整个 Widget 树
- 将 Widget 树渲染到屏幕上
Widget 树结构
在默认项目中,Widget 树的结构如下:
MyApp
(StatelessWidget)→ 应用的根 WidgetMaterialApp
→ 提供 Material Design 风格的应用框架MyHomePage
(StatefulWidget)→ 应用的主页Scaffold
→ 提供基本的页面结构(AppBar、Body 等)AppBar
→ 顶部导航栏Center
→ 居中布局组件Column
→ 垂直布局组件Text
→ 文本组件FloatingActionButton
→ 悬浮按钮
五、热重载(Hot Reload)原理与实践
Flutter 的热重载是一个非常强大的功能,它可以在不重启应用的情况下,将代码更改快速应用到运行中的应用上,大大提高开发效率。
热重载的工作原理
- 当你修改代码并触发热重载时,Flutter 会增量编译更改的 Dart 代码
- 将编译后的代码发送到正在运行的 Dart 虚拟机(VM)
- Dart VM 重新加载更新后的代码
- Flutter 框架重建 Widget 树,保留应用的状态
使用热重载
- 确保应用正在运行(
flutter run
状态) - 修改代码(例如,更改文本内容或颜色)
- 在终端中按下
r
键,或在 IDE 中点击热重载按钮
尝试修改 main.dart
中的 primarySwatch: Colors.blue
为 primarySwatch: Colors.red
,然后触发热重载,观察应用主题颜色的变化。