Flutter 笔记(上)
一、环境配置
1. 环境安装
Windows 安装步骤
-
下载 Flutter SDK
- 访问 Flutter 官网
- 下载稳定版 ZIP 文件
- 解压到合适的位置(如
C:\src\flutter)
-
配置环境变量
- 打开系统环境变量设置
- 在 Path 中添加:
C:\src\flutter\bin - 重启命令行工具使环境变量生效
-
运行环境诊断
flutter doctor- 检查所有依赖是否正确安装
- 根据提示安装缺失的组件(如 Chrome、VS Code 等)
Mac 安装步骤
-
下载 Flutter SDK
- 访问 Flutter 官网
- 下载稳定版 ZIP 文件
- 解压到合适位置(如
~/development/flutter)
-
配置环境变量
- 编辑
~/.zshrc或~/.bash_profile - 添加:
export PATH="$PATH:~/development/flutter/bin" - 运行
source ~/.zshrc使配置生效
- 编辑
-
运行环境诊断
flutter doctor
2. 创建 Flutter 项目
命令行创建项目
# 创建新项目
flutter create project_name
# 进入项目目录
cd project_name
# 启用 Web 支持(如果未启用)
flutter config --enable-web
# 运行项目(Web 平台)
flutter run -d chrome
# 或者指定其他浏览器
flutter run -d web-server
项目创建选项
# 创建带组织名称的项目
flutter create --org com.example project_name
# 创建使用特定语言的项目
flutter create --platforms=web project_name
二、项目结构详解
3. 应用目录结构
project_name/
├── .dart_tool/ # Dart 工具生成文件
├── .idea/ # IDE 配置文件
├── build/ # 构建输出目录
├── lib/ # 源代码目录
│ └── main.dart # 应用入口文件
├── test/ # 测试文件目录
├── web/ # Web 平台资源
│ ├── index.html # Web 入口 HTML
│ ├── favicon.png # 网站图标
│ └── manifest.json # Web 应用配置
├── .gitignore # Git 忽略配置
├── .metadata # Flutter 元数据
├── analysis_options.yaml # 代码分析配置
├── pubspec.yaml # 依赖配置
├── pubspec.lock # 依赖锁定文件
└── README.md # 项目说明文档
核心目录详解
lib/ 目录
这是你编写 Dart 代码的主要位置
main.dart- 应用程序的入口文件,包含main()函数- 可以创建子文件夹组织代码:
lib/screens/- 页面文件lib/widgets/- 自定义组件lib/models/- 数据模型lib/utils/- 工具函数
web/ 目录
Web 平台特定的文件
index.html- 网页的 HTML 模板manifest.json- PWA(渐进式 Web 应用)配置favicon.png- 网站图标- 可以在这里添加自定义的 CSS、JavaScript 等
test/ 目录
存放单元测试和组件测试代码
- 测试文件命名格式:
xxx_test.dart
重要配置文件
pubspec.yaml - 项目配置文件
name: project_name # 项目名称
description: A new Flutter project.
version: 1.0.0+1 # 版本号
environment:
sdk: '>=3.0.0 <4.0.0' # Dart SDK 版本要求
dependencies: # 项目依赖
flutter:
sdk: flutter
cupertino_icons: ^1.0.2 # iOS 风格图标
dev_dependencies: # 开发依赖
flutter_test:
sdk: flutter
flutter:
uses-material-design: true # 启用 Material Design
# assets: # 资源文件
# - images/
# - fonts/
pubspec.lock
- 自动生成,记录依赖的具体版本
- 不要手动修改
- 确保团队成员使用相同版本的依赖
analysis_options.yaml
配置代码风格和静态分析规则
include: package:flutter_lints/flutter.yaml
linter:
rules:
- prefer_const_constructors
- avoid_print
自动生成的文件(无需手动修改)
.dart_tool/- Dart 分析工具的缓存.idea/- IntelliJ IDEA / Android Studio 的配置build/- 编译后的文件,运行flutter clean可删除.metadata- Flutter 项目的元信息flutter_core.iml- IntelliJ 的模块配置文件
三、核心概念
4. 应用启动与 Widget
main() 函数与 runApp()
应用启动流程:
void main() {
runApp(const MyApp());
}
详细说明:
-
main()函数- Dart 程序的唯一入口点
- 程序从这里开始执行
- 必须是顶级函数(不在类中)
- 返回类型为
void
-
runApp(Widget app)函数- Flutter 框架提供的启动函数
- 将传入的 Widget 设为根组件
- 创建 Widget 树并渲染到屏幕
- 初始化 Flutter 的渲染引擎
- 绑定到原生平台
扩展用法:
void main() {
// 初始化 Flutter 绑定
WidgetsFlutterBinding.ensureInitialized();
// 可以在这里做一些初始化工作
// 例如:设置屏幕方向、加载配置等
runApp(const MyApp());
}
Widget 的核心概念
什么是 Widget?
Widget 是 Flutter 中最核心的概念,可以理解为"组件"或"小部件"。
核心特性:
- 一切皆 Widget - Flutter 中所有的 UI 元素都是 Widget
- 不可变性(Immutable) - Widget 对象一旦创建就不能修改
- 声明式 - 描述 UI 应该"是什么",而不是"怎么做"
- 轻量级 - Widget 只是配置信息,创建和销毁成本很低
Widget 树的概念:
MaterialApp
└─ Scaffold
├─ AppBar
│ └─ Text
└─ Center
└─ Column
├─ Text
└─ ElevatedButton
└─ Text
Flutter 通过嵌套 Widget 构建 UI,形成树状结构。
三棵树的关系:
- Widget 树 - 配置信息(轻量、不可变)
- Element 树 - Widget 的实例,管理 Widget 生命周期
- RenderObject 树 - 实际的渲染对象(重量级)
提示:当 UI 需要更新时,Flutter 只重建 Widget 树,通过对比来更新 Element 树和 RenderObject 树。
StatelessWidget(无状态组件)
定义:
无状态组件是不需要维护状态的组件,一旦创建后其属性就不会改变。
使用场景:
- 展示静态内容(如文本、图标)
- 不需要用户交互的 UI
- 只依赖传入参数的组件
创建方式:
class MyWidget extends StatelessWidget {
// 1. 构造函数(可选参数)
const MyWidget({super.key});
// 2. build 方法(必须实现)
Widget build(BuildContext context) {
return Container(
child: Text('Hello Flutter'),
);
}
}
带参数的无状态组件:
class GreetingWidget extends StatelessWidget {
// 定义属性(必须是 final)
final String name;
final int age;
// 构造函数
const GreetingWidget({
super.key,
required this.name,
required this.age,
});
Widget build(BuildContext context) {
return Column(
children: [
Text('你好,$name'),
Text('年龄:$age 岁'),
],
);
}
}
// 使用
GreetingWidget(name: '张三', age: 18)
关键点:
- 所有属性必须是
final - 构造函数使用
const可以提高性能 - 只有一个
build()方法 build()方法每次都返回新的 Widget 树
StatefulWidget(有状态组件)
定义:
有状态组件可以在运行时改变其状态,状态改变时 UI 会自动更新。
使用场景:
- 需要用户交互(按钮点击、输入等)
- 需要根据时间或网络请求更新 UI
- 需要动画效果
- 表单、计数器、复选框等
创建方式:
StatefulWidget 需要创建两个类:
// 1. StatefulWidget 类(不可变)
class CounterWidget extends StatefulWidget {
const CounterWidget({super.key});
// 创建 State 对象
State<CounterWidget> createState() => _CounterWidgetState();
}
// 2. State 类(可变)
class _CounterWidgetState extends State<CounterWidget> {
// 定义状态变量(可以修改)
int _counter = 0;
// 定义方法来修改状态
void _incrementCounter() {
setState(() {
// setState 会触发 build 方法重新执行
_counter++;
});
}
Widget build(BuildContext context) {
return Column(
children: [
Text('计数:$_counter'),
ElevatedButton(
onPressed: _incrementCounter,
child: Text('点击 +1'),
),
],
);
}
}
完整示例(带参数的有状态组件):
class TodoItem extends StatefulWidget {
final String title; // Widget 的属性(不可变)
const TodoItem({super.key, required this.title});
State<TodoItem> createState() => _TodoItemState();
}
class _TodoItemState extends State<TodoItem> {
bool _isCompleted = false; // State 的属性(可变)
void _toggleComplete() {
setState(() {
_isCompleted = !_isCompleted;
});
}
Widget build(BuildContext context) {
return ListTile(
title: Text(
widget.title, // 通过 widget 访问 StatefulWidget 的属性
style: TextStyle(
decoration: _isCompleted
? TextDecoration.lineThrough
: null,
),
),
trailing: Checkbox(
value: _isCompleted,
onChanged: (value) => _toggleComplete(),
),
);
}
}
关键点:
- StatefulWidget 类本身是不可变的
- State 类持有可变的状态
- 使用
setState()来更新状态和 UI - 通过
widget.属性名访问 StatefulWidget 的属性 - State 类名通常以下划线开头(私有)
setState() 详解
作用:
通知 Flutter 框架状态已改变,需要重新构建 UI。
用法:
setState(() {
// 在这里修改状态变量
_counter++;
_isVisible = !_isVisible;
});
重要原则:
- 只能在 State 对象中调用
- 必须在回调函数中修改状态
- 调用后会触发
build()方法 - 不要在
build()方法中调用setState()
错误示例:
// 错误:直接修改,不会更新 UI
_counter++;
// 错误:在 setState 外部修改
_counter++;
setState(() {});
// 错误:在 build 中调用(会导致无限循环)
Widget build(BuildContext context) {
setState(() { // 不要这样做
_counter++;
});
return Text('$_counter');
}
正确示例:
void _updateCounter() {
setState(() {
_counter++; // 在 setState 中修改
});
}
BuildContext 详解
定义:
BuildContext 是 Widget 在 Widget 树中位置的句柄。
作用:
- 定位 Widget 在树中的位置
- 向上查找父级 Widget
- 访问主题、导航器等全局信息
常见用法:
- 获取主题数据
Widget build(BuildContext context) {
// 获取当前主题
final theme = Theme.of(context);
return Text(
'Hello',
style: TextStyle(color: theme.primaryColor),
);
}
- 获取屏幕尺寸
Widget build(BuildContext context) {
final screenSize = MediaQuery.of(context).size;
final screenWidth = screenSize.width;
final screenHeight = screenSize.height;
return Container(
width: screenWidth * 0.8,
height: screenHeight * 0.5,
);
}
- 导航到新页面
void _navigateToNextPage(BuildContext context) {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => NextPage()),
);
}
- 显示 SnackBar
void _showMessage(BuildContext context) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('操作成功')),
);
}
注意事项:
- 每个 Widget 的
build()方法都会接收一个context参数 - 不要在异步操作后使用过期的
context - 某些方法(如
Navigator.of(context))需要特定的父级 Widget
生命周期方法
定义:
StatefulWidget 的 State 对象在其生命周期中会调用一系列方法,了解这些方法有助于在合适的时机执行操作。
完整生命周期流程:
class LifecycleDemo extends StatefulWidget {
const LifecycleDemo({super.key});
State<LifecycleDemo> createState() => _LifecycleDemoState();
}
class _LifecycleDemoState extends State<LifecycleDemo> {
// 1. 构造函数(最先执行)
_LifecycleDemoState() {
print('1. 构造函数');
}
// 2. initState(初始化状态,只执行一次)
void initState() {
super.initState();
print('2. initState - 初始化数据、订阅、启动动画');
// 适合做:初始化数据、订阅Stream、启动定时器、网络请求
}
// 3. didChangeDependencies(依赖变化时调用)
void didChangeDependencies() {
super.didChangeDependencies();
print('3. didChangeDependencies - InheritedWidget 变化');
// 适合做:依赖InheritedWidget的数据变化处理
}
// 4. build(构建UI,会多次执行)
Widget build(BuildContext context) {
print('4. build - 构建UI');
return Container(child: Text('生命周期演示'));
}
// 5. didUpdateWidget(Widget配置更新时调用)
void didUpdateWidget(LifecycleDemo oldWidget) {
super.didUpdateWidget(oldWidget);
print('5. didUpdateWidget - Widget重新配置');
// 适合做:比较新旧Widget,根据变化更新状态
}
// 6. setState(触发重新构建)
void _updateState() {
setState(() {
print('6. setState - 触发rebuild');
});
}
// 7. deactivate(Widget从树中移除时调用)
void deactivate() {
print('7. deactivate - 从树中移除');
super.deactivate();
}
// 8. dispose(销毁时调用,只执行一次)
void dispose() {
print('8. dispose - 清理资源');
// 适合做:取消订阅、释放资源、停止动画、关闭Stream
super.dispose();
}
}
常用生命周期方法:
1. initState()
- 在 State 对象被插入树时调用(只执行一次)
- 适合初始化数据、订阅、启动动画
void initState() {
super.initState();
_controller = AnimationController(vsync: this);
_loadData();
}
2. dispose()
- 在 State 对象被永久移除时调用(只执行一次)
- 必须清理资源,避免内存泄漏
void dispose() {
_controller.dispose();
_subscription.cancel();
super.dispose();
}
3. didChangeDependencies()
- 依赖的 InheritedWidget 变化时调用
- initState 后会立即调用一次
void didChangeDependencies() {
super.didChangeDependencies();
final theme = Theme.of(context);
// 使用主题数据
}
实际应用示例:
class TimerWidget extends StatefulWidget {
_TimerWidgetState createState() => _TimerWidgetState();
}
class _TimerWidgetState extends State<TimerWidget> {
Timer? _timer;
int _counter = 0;
void initState() {
super.initState();
// 启动定时器
_timer = Timer.periodic(Duration(seconds: 1), (timer) {
setState(() {
_counter++;
});
});
}
void dispose() {
// 停止定时器,释放资源
_timer?.cancel();
super.dispose();
}
Widget build(BuildContext context) {
return Text('计时:$_counter 秒');
}
}
Material 库
Flutter 的 UI 库:
Flutter 提供了两套完整的 UI 组件库:
-
Material Design - Google 的设计语言(Android 风格)
- 现代、扁平化设计
- 适用于 Android、Web、桌面应用
-
Cupertino - Apple 的设计语言(iOS 风格)
- 适用于 iOS 和 macOS 应用
导入 Material 库:
import 'package:flutter/material.dart';
基础应用结构:
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
// 根组件
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
return MaterialApp(
// 应用标题
title: 'Flutter Demo',
// 主题配置
theme: ThemeData(
primarySwatch: Colors.blue,
brightness: Brightness.light,
),
// 暗色主题
darkTheme: ThemeData(
brightness: Brightness.dark,
),
// 首页
home: const HomePage(),
// 是否显示调试标签
debugShowCheckedModeBanner: false,
);
}
}
// 首页
class HomePage extends StatelessWidget {
const HomePage({super.key});
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('首页'),
),
body: const Center(
child: Text('Hello Flutter'),
),
);
}
}
MaterialApp 常用属性:
title- 应用标题(在任务管理器中显示)theme- 亮色主题darkTheme- 暗色主题home- 首页 Widgetroutes- 路由表(页面导航)initialRoute- 初始路由debugShowCheckedModeBanner- 是否显示 DEBUG 标签
常用的 Material 组件:
Scaffold- 页面脚手架AppBar- 顶部导航栏FloatingActionButton- 悬浮按钮Drawer- 抽屉菜单BottomNavigationBar- 底部导航栏Card- 卡片Dialog- 对话框SnackBar- 底部提示条
498

被折叠的 条评论
为什么被折叠?



