第1章:Flutter开发环境搭建与工具链
1.1 Flutter简介与优势
Flutter是Google推出的开源UI工具包,用于从单一代码库构建编译为原生性能的移动、Web和桌面应用程序。Flutter的核心优势包括:
- 跨平台一致性:一套代码运行在iOS、Android、Web、Desktop
- 高性能:直接编译为原生ARM代码,无需JavaScript桥接
- 热重载:快速开发调试,提升开发效率
- 丰富的UI组件:Material Design和Cupertino风格组件
- 活跃的生态:Google支持,社区活跃,插件丰富
1.2 Flutter SDK安装与配置
1.2.1 Windows环境安装
系统要求:
- Windows 10或更高版本(64位)
- 磁盘空间:1.64GB(不包括IDE/工具的磁盘空间)
- Git for Windows
安装步骤:
- 下载Flutter SDK
# 方法1:直接下载压缩包
# 访问 https://flutter.dev/docs/get-started/install/windows
# 下载flutter_windows_3.16.0-stable.zip
# 方法2:使用Git克隆(推荐)
git clone https://github.com/flutter/flutter.git -b stable
- 解压并配置环境变量
# 解压到合适目录,如:C:\flutter
# 添加C:\flutter\bin到系统PATH环境变量
- 验证安装
flutter --version
flutter doctor
常见问题解决:
# 问题:'flutter' 不是内部或外部命令
# 解决:检查PATH环境变量是否正确添加Flutter的bin目录
# 问题:网络连接问题
# 解决:配置镜像源
export PUB_HOSTED_URL=https://pub.flutter-io.cn
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
1.2.2 macOS环境安装
系统要求:
- macOS 10.14或更高版本
- 磁盘空间:2.8GB
- Xcode(用于iOS开发)
安装步骤:
- 使用Homebrew安装(推荐)
# 安装Homebrew(如果未安装)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# 安装Flutter
brew install --cask flutter
# 或者手动下载
curl -O https://storage.googleapis.com/flutter_infra_release/releases/stable/macos/flutter_macos_3.16.0-stable.zip
unzip flutter_macos_3.16.0-stable.zip
- 添加到PATH
# 编辑shell配置文件(~/.zshrc 或 ~/.bash_profile)
export PATH="$PATH:/path/to/flutter/bin"
# 重新加载配置
source ~/.zshrc
- 配置iOS开发环境
# 安装Xcode
# 从App Store安装Xcode
# 安装Xcode命令行工具
sudo xcode-select --install
# 同意Xcode许可证
sudo xcodebuild -license accept
1.2.3 Linux环境安装
系统要求:
- Linux(64位)
- 依赖库:bash、curl、file、git、mkdir、rm、unzip、which、xz-utils
安装步骤:
- 安装依赖
# Ubuntu/Debian
sudo apt-get update
sudo apt-get install curl git unzip xz-utils zip libglu1-mesa
# CentOS/RHEL
sudo yum install curl git unzip xz zip mesa-libGLU
- 下载并安装Flutter
# 下载Flutter
wget https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_3.16.0-stable.tar.xz
# 解压
tar xf flutter_linux_3.16.0-stable.tar.xz
# 添加到PATH
export PATH="$PATH:`pwd`/flutter/bin"
1.3 开发环境配置
1.3.1 Android Studio配置
安装Android Studio:
- 下载并安装Android Studio
- 启动Android Studio,完成初始设置
- 安装Flutter和Dart插件
配置步骤:
# 1. 打开Android Studio
# 2. 进入Preferences/Settings -> Plugins
# 3. 搜索并安装Flutter插件(会自动安装Dart插件)
# 4. 重启Android Studio
Android SDK配置:
# 在Android Studio中:
# Tools -> SDK Manager
# 安装以下组件:
# - Android SDK Platform-Tools
# - Android SDK Build-Tools
# - Android API Level 34(或最新版本)
创建第一个Flutter项目:
// 在Android Studio中创建新项目
// File -> New -> New Flutter Project
// 选择Flutter Application
// 配置项目名称和位置
// 项目结构说明
flutter_app/
├── android/ # Android原生代码
├── ios/ # iOS原生代码
├── lib/ # Dart代码主目录
│ └── main.dart # 应用入口文件
├── test/ # 测试文件
├── web/ # Web平台支持
├── pubspec.yaml # 项目配置文件
└── README.md # 项目说明
1.3.2 VS Code配置
安装VS Code和插件:
- 安装Visual Studio Code
- 安装必要插件
# 推荐插件列表:
# - Flutter (自动包含Dart插件)
# - Flutter Widget Snippets
# - Awesome Flutter Snippets
# - Dart Data Class Generator
# - Flutter Tree
VS Code配置文件示例:
// .vscode/settings.json
{
"dart.flutterSdkPath": "/path/to/flutter",
"dart.lineLength": 100,
"dart.showTodos": true,
"dart.openDevTools": "flutter",
"editor.rulers": [100],
"editor.tabCompletion": "on",
"flutter.debugShowInspectorByDefault": true
}
快捷键配置:
// .vscode/keybindings.json
[
{
"key": "ctrl+f5",
"command": "flutter.hotReload"
},
{
"key": "ctrl+shift+f5",
"command": "flutter.hotRestart"
}
]
1.4 模拟器与真机调试设置
1.4.1 Android模拟器配置
创建Android虚拟设备:
# 方法1:通过Android Studio创建
# Tools -> AVD Manager -> Create Virtual Device
# 方法2:通过命令行创建
# 列出可用的系统镜像
$ANDROID_HOME/tools/bin/avdmanager list targets
# 创建AVD
$ANDROID_HOME/tools/bin/avdmanager create avd -n flutter_emulator -k "system-images;android-34;google_apis;x86_64"
# 启动模拟器
$ANDROID_HOME/emulator/emulator -avd flutter_emulator
模拟器性能优化:
# 启用硬件加速
# Windows: 确保启用Hyper-V或HAXM
# macOS: 确保启用Hypervisor framework
# Linux: 确保启用KVM
# 优化启动参数
emulator -avd flutter_emulator -gpu host -memory 4096
1.4.2 iOS模拟器配置(仅macOS)
# 启动iOS模拟器
open -a Simulator
# 或通过Xcode启动
# Xcode -> Developer Tools -> Simulator
# 命令行启动特定设备
xcrun simctl boot "iPhone 15 Pro"
xcrun simctl list devices
1.4.3 真机调试设置
Android真机调试:
# 1. 启用开发者选项
# 设置 -> 关于手机 -> 连续点击7次版本号
# 2. 启用USB调试
# 设置 -> 开发者选项 -> USB调试
# 3. 连接设备并验证
adb devices
# 4. 安装应用到设备
flutter run
iOS真机调试:
- 配置开发者账号
- 生成证书和描述文件
- 在Xcode中配置签名
# 检查连接的iOS设备
flutter devices
# 运行到iOS设备
flutter run -d [device-id]
常见真机调试问题:
// 问题1:设备未授权
// 解决:检查设备是否显示授权弹窗,点击允许
// 问题2:签名错误(iOS)
// 解决:在Xcode中正确配置开发者账号和签名证书
// 问题3:网络权限问题
// Android: 在android/app/src/main/AndroidManifest.xml添加
<uses-permission android:name="android.permission.INTERNET" />
// iOS: 在ios/Runner/Info.plist添加网络权限配置
1.5 Flutter Doctor命令详解
Flutter Doctor是Flutter提供的诊断工具,用于检查开发环境配置。
基本用法:
# 检查Flutter环境
flutter doctor
# 显示详细信息
flutter doctor -v
# 检查特定平台
flutter doctor --android-licenses
常见输出解读:
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.16.0, on macOS 14.0, locale zh-CN)
[✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 15.0)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2023.1)
[✓] VS Code (version 1.84.0)
[✓] Connected device (2 available)
[✓] HTTP Host Availability
# 符号说明:
# [✓] - 配置正确
# [!] - 有警告,但不影响开发
# [✗] - 有错误,需要修复
常见问题修复:
# 问题1:Android licenses not accepted
flutter doctor --android-licenses
# 按提示接受所有许可证
# 问题2:Xcode not configured
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
sudo xcodebuild -license accept
# 问题3:Flutter SDK版本过旧
flutter upgrade
# 问题4:Dart SDK version不匹配
flutter channel stable
flutter upgrade
1.6 热重载与热重启机制
热重载(Hot Reload)和热重启(Hot Restart)是Flutter开发的核心特性。
1.6.1 热重载机制原理
热重载通过以下步骤实现:
- 代码变更检测:监听文件系统变化
- 增量编译:只编译修改的代码
- 状态保持:保持应用当前状态
- UI更新:重新构建widget树
// 示例:热重载演示
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Hot Reload Demo',
home: CounterPage(),
);
}
}
class CounterPage extends StatefulWidget {
@override
_CounterPageState createState() => _CounterPageState();
}
class _CounterPageState extends State<CounterPage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++; // 修改这里的逻辑,保存文件触发热重载
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('热重载演示'), // 修改这里的文本,观察热重载效果
backgroundColor: Colors.blue, // 修改颜色测试热重载
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'按钮点击次数:', // 修改这里测试热重载
style: TextStyle(fontSize: 18),
),
Text(
'$_counter', // 计数器状态在热重载时会保持
style: Theme.of(context).textTheme.headlineMedium,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
1.6.2 热重载触发方式
# 方法1:IDE快捷键
# Android Studio: Ctrl+\ (Windows/Linux) 或 Cmd+\ (macOS)
# VS Code: Ctrl+F5
# 方法2:命令行
flutter run
# 在运行时按 'r' 键触发热重载
# 在运行时按 'R' 键触发热重启
# 方法3:自动热重载
flutter run --hot
1.6.3 热重载限制与注意事项
不支持热重载的情况:
// 1. 全局变量和静态字段
class GlobalData {
static int count = 0; // 修改这个值不会热重载
}
// 2. main()函数
void main() {
runApp(MyApp()); // 修改这里需要热重启
}
// 3. initState()方法
class MyWidget extends StatefulWidget {
@override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
@override
void initState() {
super.initState();
// 修改这里的逻辑需要热重启
print("Widget initialized");
}
@override
Widget build(BuildContext context) {
return Container(); // 修改这里可以热重载
}
}
// 4. 枚举类型修改
enum Status {
loading,
success,
error // 添加新的枚举值需要热重启
}
热重载最佳实践:
// 1. 合理组织Widget结构
class MyPage extends StatefulWidget {
@override
_MyPageState createState() => _MyPageState();
}
class _MyPageState extends State<MyPage> {
// 将UI逻辑拆分成小的方法,便于热重载测试
Widget _buildHeader() {
return AppBar(
title: Text('我的页面'),
);
}
Widget _buildBody() {
return Center(
child: Text('页面内容'),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: _buildHeader(),
body: _buildBody(),
);
}
}
// 2. 使用const构造函数提高性能
class MyStaticWidget extends StatelessWidget {
const MyStaticWidget({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const Text('静态内容');
}
}
1.7 常见环境问题排查与解决方案
1.7.1 网络相关问题
# 问题:无法下载依赖包
# 解决方案1:配置镜像源
flutter pub cache repair
# 解决方案2:手动设置代理
export HTTP_PROXY=http://proxy.example.com:8080
export HTTPS_PROXY=http://proxy.example.com:8080
# 解决方案3:使用国内镜像
export PUB_HOSTED_URL=https://pub.flutter-io.cn
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
1.7.2 权限相关问题
# Android权限问题
# 在android/app/src/main/AndroidManifest.xml中添加权限
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
# iOS权限问题
# 在ios/Runner/Info.plist中添加权限说明
<key>NSCameraUsageDescription</key>
<string>This app needs camera access to take photos</string>
1.7.3 构建错误解决
// 常见错误1:版本冲突
// pubspec.yaml
dependencies:
flutter:
sdk: flutter
some_package: ^2.0.0 # 确保版本兼容
// 解决方案
flutter pub deps // 查看依赖树
flutter pub upgrade // 升级依赖
flutter clean // 清理构建缓存
flutter pub get // 重新获取依赖
// 常见错误2:Gradle构建失败
// android/build.gradle
buildscript {
ext.kotlin_version = '1.8.0' // 更新Kotlin版本
dependencies {
classpath 'com.android.tools.build:gradle:8.0.0' // 更新Gradle版本
}
}
本章小结
本章介绍了Flutter开发环境的完整搭建过程,包括:
- 跨平台SDK安装:覆盖Windows、macOS、Linux三大平台
- IDE配置:Android Studio和VS Code的详细设置
- 调试环境:模拟器和真机调试的配置方法
- 诊断工具:Flutter Doctor的使用和问题解决
- 开发效率:热重载机制的原理和最佳实践
练习题
-
环境搭建练习
- 在你的系统上完整安装Flutter开发环境
- 使用Flutter Doctor检查环境配置
- 创建并运行第一个Flutter应用
-
调试环境配置
- 配置Android模拟器并运行应用
- 如果有真机,配置真机调试环境
- 测试热重载功能
-
问题排查练习
- 故意制造环境问题(如删除PATH配置)
- 使用本章方法进行问题排查和修复
思考问题
- 为什么Flutter能够实现热重载功能?其技术原理是什么?
- 在团队开发中,如何确保所有成员的开发环境一致?
- 热重载和热重启的区别是什么?什么情况下必须使用热重启?
第2章:Dart语言精要
2.1 Dart语言特性与语法基础
Dart是Google开发的客户端优化语言,专为快速应用开发而设计。作为Flutter的编程语言,掌握Dart是Flutter开发的基础。
2.1.1 Dart语言特点
// Dart语言核心特性演示
void main() {
// 1. 强类型系统 + 类型推断
String name = "Flutter"; // 显式类型声明
var age = 25; // 类型推断,编译时确定为int
// 2. 面向对象编程
var person = Person("Alice", 30);
person.introduce();
// 3. 函数式编程支持
var numbers = [1, 2, 3, 4, 5];
var doubled = numbers.map((n) => n * 2).toList();
print("Doubled: $doubled");
// 4. 异步编程原生支持
fetchUserData();
// 5. 空安全(Null Safety)
String? nullableName; // 可空类型
String nonNullName = "Flutter"; // 非空类型
print("nullableName: $nullableName"); // 输出: null
print("nonNullName: $nonNullName");
}
// 类定义
class Person {
String name;
int age;
// 构造函数
Person(this.name, this.age);
// 方法
void introduce() {
print("Hi, I'm $name, $age years old.");
}
}
// 异步函数
Future<void> fetchUserData() async {
print("Fetching user data...");
await Future.delayed(Duration(seconds: 1));
print("User data loaded!");
}
2.1.2 基本语法结构
注释和文档:
// 单行注释
/*
多行注释
可以跨越多行
*/
/// 文档注释 - 用于生成API文档
/// 这是一个计算函数
///
/// [a] 第一个参数
/// [b] 第二个参数
/// 返回两数之和
int add(int a, int b) {
return a + b;
}
/**
* 传统的多行文档注释
* 也被支持
*/
基本数据类型:
void main() {
// 数字类型
int integer = 42;
double floating = 3.14;
num number = 42; // int和double的父类型
// 字符串类型
String singleQuote = 'Hello';
String doubleQuote = "World";
String multiLine = '''
这是一个
多行字符串
''';
// 布尔类型
bool isTrue = true;
bool isFalse = false;
// 字符串插值
print("Number: $number, Is true: $isTrue");
print("Expression: ${1 + 1}");
// 原始字符串(不处理转义字符)
String rawString = r'This is a raw string with \n';
print(rawString);
// 类型检查和转换
print("integer is int: ${integer is int}");
print("integer as num: ${integer as num}");
}
操作符详解:
void demonstrateOperators() {
// 算术操作符
int a = 10, b = 3;
print("加法: ${a + b}"); // 13
print("减法: ${a - b}"); // 7
print("乘法: ${a * b}"); // 30
print("除法: ${a / b}"); // 3.3333...
print("整除: ${a ~/ b}"); // 3
print("取模: ${a % b}"); // 1
// 比较操作符
print("等于: ${a == b}"); // false
print("不等于: ${a != b}"); // true
print("大于: ${a > b}"); // true
print("小于等于: ${a <= b}"); // false
// 逻辑操作符
bool x = true, y = false;
print("逻辑与: ${x && y}"); // false
print("逻辑或: ${x || y}"); // true
print("逻辑非: ${!x}"); // false
// 位操作符
int m = 5, n = 3; // 101, 011 in binary
print("按位与: ${m & n}"); // 1 (001)
print("按位或: ${m | n}"); // 7 (111)
print("按位异或: ${m ^ n}"); // 6 (110)
print("按位取反: ${~m}"); // -6
print("左移: ${m << 1}"); // 10
print("右移: ${m >> 1}"); // 2
// 赋值操作符
int value = 10;
value += 5; // value = value + 5
print("加法赋值: $value"); // 15
value *= 2; // value = value * 2
print("乘法赋值: $value"); // 30
// 空合并操作符
String? nullableString;
String result = nullableString ?? "默认值";
print("空合并: $result"); // 默认值
// 条件表达式
int score = 85;
String grade = score >= 90 ? "A" : score >= 80 ? "B" : "C";
print("等级: $grade"); // B
// 级联操作符
var list = <int>[]
..add(1)
..add(2)
..add(3);
print("级联操作: $list"); // [1, 2, 3]
}
2.2 变量、函数、类与继承
2.2.1 变量声明与作用域
// 全局变量
String globalVar = "I'm global";
late String lateGlobalVar; // 延迟初始化
void main() {
// 局部变量声明方式
// 1. 显式类型声明
int explicitInt = 42;
String explicitString = "Hello";
// 2. 类型推断
var inferredInt = 42; // 推断为int
var inferredString = "Hello"; // 推断为String
// 3. 动态类型
dynamic dynamicVar = 42;
dynamicVar = "Now I'm a string"; // 可以改变类型
// 4. 常量声明
const int constantInt = 42; // 编译时常量
final int finalInt = DateTime.now().millisecondsSinceEpoch; // 运行时常量
// 5. 可空类型
int? nullableInt; // 可以为null
int nonNullableInt = 42; // 不能为null
// 作用域演示
{
String blockScoped = "I'm in a block";
print(blockScoped); // 可以访问
}
// print(blockScoped); // 错误:超出作用域
// Late变量使用
late String expensiveString;
// 只有在需要时才初始化
if (someCondition()) {
expensiveString = performExpensiveOperation();
print(expensiveString);
}
}
bool someCondition() => true;
String performExpensiveOperation() => "Expensive result";
// 变量的获取器和设置器
class Rectangle {
double _width = 0;
double _height = 0;
// 获取器
double get area => _width * _height;
// 设置器
set width(double value) {
if (value < 0) {
throw ArgumentError("Width cannot be negative");
}
_width = value;
}
set height(double value) {
if (value < 0) {
throw ArgumentError("Height cannot be negative");
}
_height = value;
}
double get width => _width;
double get height => _height;
}
2.2.2 函数定义与调用
// 函数定义的各种形式
void main() {
// 调用各种函数
print("基本函数: ${basicFunction(5, 3)}");
print("可选参数: ${optionalParameters(10)}");
print("命名参数: ${namedParameters(a: 5, b: 3)}");
print("默认参数: ${defaultParameters(10)}");
// 匿名函数和箭头函数
var anonymousFunction = (int x) {
return x * x;
};
var arrowFunction = (int x) => x * x;
print("匿名函数: ${anonymousFunction(5)}");
print("箭头函数: ${arrowFunction(5)}");
// 高阶函数示例
var numbers = [1, 2, 3, 4, 5];
var processed = processNumbers(numbers, (x) => x * 2);
print("高阶函数: $processed");
// 闭包示例
var multiplier = createMultiplier(3);
print("闭包: ${multiplier(4)}"); // 12
}
// 1. 基本函数
int basicFunction(int a, int b) {
return a + b;
}
// 2. 可选位置参数
int optionalParameters(int a, [int? b, int c = 10]) {
return a + (b ?? 0) + c;
}
// 3. 命名参数
int namedParameters({required int a, int b = 0}) {
return a + b;
}
// 4. 默认参数值
int defaultParameters(int a, {int b = 5, int c = 10}) {
return a + b + c;
}
// 5. 高阶函数(函数作为参数)
List<int> processNumbers(List<int> numbers, int Function(int) processor) {
return numbers.map(processor).toList();
}
// 6. 闭包
Function createMultiplier(int factor) {
return (int value) => value * factor;
}
// 7. 生成器函数
Iterable<int> naturalNumbers(int max) sync* {
int current = 1;
while (current <= max) {
yield current++;
}
}
// 8. 异步生成器函数
Stream<int> asynchronousNaturals(int max) async* {
int current = 1;
while (current <= max) {
await Future.delayed(Duration(milliseconds: 100));
yield current++;
}
}
// 函数类型定义
typedef Calculator = int Function(int a, int b);
typedef StringProcessor = String Function(String input);
// 使用函数类型
class MathUtils {
static Calculator adder = (a, b) => a + b;
static Calculator multiplier = (a, b) => a * b;
static int calculate(int a, int b, Calculator calc) {
return calc(a, b);
}
}
2.2.3 类的定义与使用
// 基础类定义
class Animal {
// 私有属性(以_开头)
String _name;
int _age;
// 公共属性
String species;
// 构造函数
Animal(this._name, this._age, this.species);
// 命名构造函数
Animal.baby(String name, String species)
: _name = name,
_age = 0,
species = species;
// 工厂构造函数
factory Animal.fromJson(Map<String, dynamic> json) {
return Animal(json['name'], json['age'], json['species']);
}
// 获取器和设置器
String get name => _name;
int get age => _age;
set name(String newName) {
if (newName.isNotEmpty) {
_name = newName;
}
}
// 方法
void makeSound() {
print("$_name makes a sound");
}
void eat(String food) {
print("$_name is eating $food");
}
// 静态方法
static Animal createRandomAnimal() {
var names = ['Buddy', 'Max', 'Luna'];
var species = ['Dog', 'Cat', 'Bird'];
return Animal(
names[DateTime.now().millisecond % names.length],
DateTime.now().millisecond % 10,
species[DateTime.now().millisecond % species.length]
);
}
// 重写toString方法
@override
String toString() {
return 'Animal{name: $_name, age: $_age, species: $species}';
}
}
// 继承
class Dog extends Animal {
String breed;
// 调用父类构造函数
Dog(String name, int age, this.breed) : super(name, age, 'Dog');
// 重写方法
@override
void makeSound() {
print("$name barks: Woof! Woof!");
}
// 新增方法
void fetch() {
print("$name is fetching the ball");
}
// 方法重载(Dart不支持真正的重载,但可以用可选参数实现)
void playWith([String? toy]) {
if (toy != null) {
print("$name is playing with $toy");
} else {
print("$name is playing");
}
}
}
// 抽象类
abstract class Shape {
// 抽象方法
double calculateArea();
double calculatePerimeter();
// 具体方法
void displayInfo() {
print("Area: ${calculateArea()}, Perimeter: ${calculatePerimeter()}");
}
}
// 实现抽象类
class Circle extends Shape {
double radius;
Circle(this.radius);
@override
double calculateArea() {
return 3.14159 * radius * radius;
}
@override
double calculatePerimeter() {
return 2 * 3.14159 * radius;
}
}
// 接口(在Dart中通过abstract class或普通class实现)
abstract class Flyable {
void fly();
}
abstract class Swimmable {
void swim();
}
// 多重继承(通过mixin实现)
mixin CanFly {
void fly() {
print("Flying in the sky");
}
}
mixin CanSwim {
void swim() {
print("Swimming in water");
}
}
// 使用mixin
class Duck extends Animal with CanFly, CanSwim {
Duck(String name, int age) : super(name, age, 'Duck');
@override
void makeSound() {
print("$name quacks: Quack! Quack!");
}
}
// 使用示例
void main() {
// 创建对象
var dog = Dog("Buddy", 3, "Golden Retriever");
dog.makeSound();
dog.fetch();
dog.playWith("ball");
// 多态
Animal animal = Dog("Max", 2, "Bulldog");
animal.makeSound(); // 调用Dog的重写方法
// 抽象类
Shape circle = Circle(5.0);
circle.displayInfo();
// Mixin使用
var duck = Duck("Donald", 5);
duck.makeSound();
duck.fly();
duck.swim();
// 工厂构造函数
var animalFromJson = Animal.fromJson({
'name': 'Whiskers',
'age': 4,
'species': 'Cat'
});
print(animalFromJson);
}
2.3 异步编程:Future、async/await、Stream
异步编程是Dart和Flutter的核心特性,用于处理网络请求、文件操作、定时器等耗时操作。
2.3.1 Future基础
import 'dart:async';
import 'dart:math';
void main() async {
print("=== Future基础演示 ===");
// 基本Future使用
await demonstrateFutureBasics();
// Future错误处理
await demonstrateFutureErrorHandling();
// Future组合操作
await demonstrateFutureCombination();
}
// Future基础用法
Future<void> demonstrateFutureBasics() async {
print("\n1. 基础Future操作:");
// 方式1: 使用then()
fetchUserData(1).then((user) {
print("用户信息: $user");
});
// 方式2: 使用async/await (推荐)
String user = await fetchUserData(2);
print("用户信息: $user");
// 方式3: 创建立即完成的Future
Future<String> immediateFuture = Future.value("立即返回的值");
String result = await immediateFuture;
print("立即结果: $result");
// 方式4: 延迟Future
print("开始延迟操作...");
await Future.delayed(Duration(seconds: 1), () {
print("延迟操作完成!");
});
}
// 模拟异步获取用户数据
Future<String> fetchUserData(int userId) async {
// 模拟网络延迟
await Future.delayed(Duration(milliseconds: 500));
// 模拟随机失败
if (Random().nextBool()) {
throw Exception("网络错误: 无法获取用户 $userId 的数据");
}
return "User$userId{name: '张三', age: 25}";
}
// Future错误处理
Future<void> demonstrateFutureErrorHandling() async {
print("\n2. Future错误处理:");
// 方式1: try-catch
try {
String userData = await fetchUserData(3);
print("成功获取: $userData");
} catch (e) {
print("捕获异常: $e");
}
// 方式2: catchError
fetchUserData(4)
.then((user) => print("成功: $user"))
.catchError((error) => print("失败: $error"));
// 方式3: 超时处理
try {
String result = await fetchUserData(5).timeout(
Duration(milliseconds: 200),
onTimeout: () => throw TimeoutException("请求超时", Duration(milliseconds: 200)),
);
print("超时测试成功: $result");
} on TimeoutException catch (e) {
print("请求超时: ${e.message}");
} catch (e) {
print("其他错误: $e");
}
}
// Future组合操作
Future<void> demonstrateFutureCombination() async {
print("\n3. Future组合操作:");
// 并行执行多个Future
List<Future<String>> futures = [
fetchData("API1", 300),
fetchData("API2", 500),
fetchData("API3", 200),
];
// 等待所有Future完成
try {
List<String> results = await Future.wait(futures);
print("所有请求完成: $results");
} catch (e) {
print("有请求失败: $e");
}
// 只要有一个完成就返回
String firstResult = await Future.any(futures);
print("最快完成的请求: $firstResult");
// 链式操作
String chainResult = await fetchData("初始数据", 100)
.then((data) => processData(data))
.then((processed) => saveData(processed));
print("链式操作结果: $chainResult");
}
// 辅助函数
Future<String> fetchData(String source, int delay) async {
await Future.delayed(Duration(milliseconds: delay));
if (Random().nextDouble() < 0.2) { // 20%失败率
throw Exception("$source 请求失败");
}
return "$source 的数据";
}
Future<String> processData(String data) async {
await Future.delayed(Duration(milliseconds: 100));
return "处理后的 $data";
}
Future<String> saveData(String data) async {
await Future.delayed(Duration(milliseconds: 50));
return "已保存: $data";
}
2.3.2 Stream详解
import 'dart:async';
void main() async {
print("=== Stream演示 ===");
// 基础Stream操作
await demonstrateStreamBasics();
// Stream变换和过滤
await demonstrateStreamTransformation();
// 自定义Stream
await demonstrateCustomStream();
// StreamController使用
await demonstrateStreamController();
}
// Stream基础操作
Future<void> demonstrateStreamBasics() async {
print("\n1. Stream基础操作:");
// 创建简单的Stream
Stream<int> numberStream = Stream.fromIterable([1, 2, 3, 4, 5]);
// 方式1: 使用listen
print("使用listen监听:");
numberStream.listen(
(number) => print("接收到: $number"),
onError: (error) => print("错误: $error"),
onDone: () => print("Stream完成"),
);
// 等待一段时间让上面的Stream完成
await Future.delayed(Duration(milliseconds: 100));
// 方式2: 使用await for (推荐)
print("\n使用await for:");
await for (int number in Stream.fromIterable([6, 7, 8, 9, 10])) {
print("处理数字: $number");
}
}
// Stream变换和过滤
Future<void> demonstrateStreamTransformation() async {
print("\n2. Stream变换和过滤:");
// 创建数字流
Stream<int> numbers = Stream.periodic(
Duration(milliseconds: 200),
(index) => index + 1,
).take(10); // 只取前10个
// 变换操作
await for (String result in numbers
.where((n) => n % 2 == 0) // 过滤偶数
.map((n) => "偶数: $n") // 转换为字符串
.take(3)) { // 只取前3个
print(result);
}
// 复杂的Stream操作链
print("\n复杂操作链:");
await numbers
.where((n) => n > 3) // 大于3
.map((n) => n * n) // 平方
.distinct() // 去重
.timeout(Duration(seconds: 5)) // 超时处理
.handleError((error) { // 错误处理
print("Stream错误: $error");
return -1;
})
.forEach((value) => print("结果: $value"));
}
// 自定义Stream
Future<void> demonstrateCustomStream() async {
print("\n3. 自定义Stream:");
// 使用async*创建Stream
await for (String data in generateDataStream()) {
print("自定义Stream数据: $data");
}
}
// 生成器函数创建Stream
Stream<String> generateDataStream() async* {
for (int i = 1; i <= 5; i++) {
await Future.delayed(Duration(milliseconds: 300));
yield "数据项 $i";
if (i == 3) {
yield* generateSubStream(); // 委托给另一个Stream
}
}
}
Stream<String> generateSubStream() async* {
yield "子流数据 A";
yield "子流数据 B";
}
// StreamController使用
Future<void> demonstrateStreamController() async {
print("\n4. StreamController使用:");
// 创建StreamController
StreamController<String> controller = StreamController<String>();
// 监听Stream
StreamSubscription<String> subscription = controller.stream.listen(
(data) => print("控制器数据: $data"),
onError: (error) => print("控制器错误: $error"),
onDone: () => print("控制器完成"),
);
// 添加数据
controller.add("消息1");
controller.add("消息2");
controller.add("消息3");
// 模拟延迟添加
Timer.periodic(Duration(milliseconds: 500), (timer) {
static int count = 0;
if (count < 3) {
controller.add("定时消息 ${++count}");
} else {
timer.cancel();
controller.close(); // 关闭Stream
}
});
// 等待Stream完成
await controller.done;
// 清理
await subscription.cancel();
}
// 实际应用示例:模拟实时数据流
class DataService {
static StreamController<Map<String, dynamic>>? _controller;
// 获取实时数据流
static Stream<Map<String, dynamic>> get realTimeData {
_controller ??= StreamController<Map<String, dynamic>>.broadcast();
return _controller!.stream;
}
// 开始数据流
static void startDataStream() {
Timer.periodic(Duration(seconds: 2), (timer) {
if (_controller?.isClosed ?? true) {
timer.cancel();
return;
}
_controller?.add({
'timestamp': DateTime.now().toIso8601String(),
'value': Random().nextDouble() * 100,
'status': Random().nextBool() ? 'active' : 'inactive',
});
});
}
// 停止数据流
static void stopDataStream() {
_controller?.close();
_controller = null;
}
}
2.4 空安全(Null Safety)详解
空安全是Dart 2.12引入的重要特性,帮助开发者避免空引用异常。
2.4.1 空安全基础概念
void main() {
print("=== 空安全演示 ===");
demonstrateNullSafetyBasics();
demonstrateNullableOperators();
demonstrateNullAssertions();
demonstrateLateVariables();
}
// 空安全基础
void demonstrateNullSafetyBasics() {
print("\n1. 空安全基础:");
// 非空类型 - 不能为null
String nonNullableString = "Hello, World!";
int nonNullableInt = 42;
// 可空类型 - 可以为null
String? nullableString = null;
int? nullableInt; // 默认为null
print("非空字符串: $nonNullableString");
print("可空字符串: $nullableString");
print("可空整数: $nullableInt");
// 编译时错误示例(取消注释会报错)
// nonNullableString = null; // 错误:不能将null赋给非空类型
// print(nullableString.length); // 错误:可空类型不能直接调用方法
// 正确的处理方式
if (nullableString != null) {
print("字符串长度: ${nullableString.length}"); // 类型提升
}
}
// 空安全操作符
void demonstrateNullableOperators() {
print("\n2. 空安全操作符:");
String? nullableString;
List<String>? nullableList;
// 1. 空感知访问操作符 (?.)
print("安全访问长度: ${nullableString?.length}"); // 输出: null
print("安全访问第一个元素: ${nullableList?.first}"); // 输出: null
// 2. 空合并操作符 (??)
String result = nullableString ?? "默认值";
print("空合并结果: $result"); // 输出: 默认值
// 3. 空合并赋值操作符 (??=)
nullableString ??= "赋值的默认值";
print("空合并赋值: $nullableString"); // 输出: 赋值的默认值
// 4. 级联空感知操作符 (?..)
List<String>? optionalList = ["item1", "item2"];
optionalList?..add("item3")..add("item4");
print("级联操作结果: $optionalList");
// 5. 空感知索引操作符 (?[])
List<String>? items = ["first", "second"];
print("安全索引访问: ${items?[0]}"); // 输出: first
items = null;
print("空列表安全访问: ${items?[0]}"); // 输出: null
}
// 空断言和类型检查
void demonstrateNullAssertions() {
print("\n3. 空断言和类型检查:");
String? possiblyNullString = "Not null";
// 1. 空断言操作符 (!) - 谨慎使用
if (possiblyNullString != null) {
String definitelyNotNull = possiblyNullString!;
print("断言非空: $definitelyNotNull");
}
// 2. 类型检查和转换
Object? someObject = "Hello";
if (someObject is String) {
// 类型提升 - someObject现在被认为是String类型
print("类型提升: ${someObject.toUpperCase()}");
}
// 3. 安全类型转换
String? safeString = someObject as String?;
print("安全转换: $safeString");
// 4. 复杂的空检查
String? getName() => Random().nextBool() ? "Alice" : null;
String name = getName() ?? "Unknown";
print("获取姓名: $name");
}
// Late变量
void demonstrateLateVariables() {
print("\n4. Late变量:");
// Late变量示例
late String expensiveValue;
late final String computedValue;
// 延迟初始化函数
String expensiveComputation() {
print("执行昂贵的计算...");
return "计算结果";
}
// 只有在访问时才会初始化
print("准备访问late变量");
expensiveValue = expensiveComputation();
print("Late变量值: $expensiveValue");
// Late final变量
computedValue = "一次性计算的值";
print("Late final值: $computedValue");
// computedValue = "尝试再次赋值"; // 错误:final变量不能重新赋值
}
// 实际应用示例
class UserService {
// 私有的可空字段
User? _currentUser;
// 公共的非空访问器
User get currentUser {
final user = _currentUser;
if (user == null) {
throw StateError('没有当前用户');
}
return user;
}
// 安全的用户访问
User? get currentUserOrNull => _currentUser;
// 登录方法
Future<void> login(String username, String password) async {
// 模拟网络请求
await Future.delayed(Duration(seconds: 1));
if (username.isNotEmpty && password.isNotEmpty) {
_currentUser = User(username, "$username@example.com");
} else {
throw ArgumentError('用户名和密码不能为空');
}
}
// 登出方法
void logout() {
_currentUser = null;
}
// 安全的用户操作
String? getUserEmail() {
return _currentUser?.email;
}
// 使用空合并操作符提供默认值
String getDisplayName() {
return _currentUser?.name ?? '匿名用户';
}
}
class User {
final String name;
final String email;
User(this.name, this.email);
@override
String toString() => 'User{name: $name, email: $email}';
}
// 空安全最佳实践示例
class ShoppingCart {
final List<CartItem> _items = [];
// 安全地添加商品
void addItem(String? productName, double? price, int? quantity) {
// 使用空检查和默认值
final name = productName?.trim();
if (name == null || name.isEmpty) {
throw ArgumentError('商品名称不能为空');
}
final validPrice = price ?? 0.0;
if (validPrice <= 0) {
throw ArgumentError('价格必须大于0');
}
final validQuantity = quantity ?? 1;
if (validQuantity <= 0) {
throw ArgumentError('数量必须大于0');
}
_items.add(CartItem(name, validPrice, validQuantity));
}
// 安全地获取商品
CartItem? getItem(int index) {
if (index >= 0 && index < _items.length) {
return _items[index];
}
return null;
}
// 计算总价
double get totalPrice {
return _items.fold(0.0, (sum, item) => sum + item.totalPrice);
}
// 获取商品数量
int get itemCount => _items.length;
// 安全地移除商品
bool removeItem(String productName) {
final index = _items.indexWhere((item) => item.name == productName);
if (index != -1) {
_items.removeAt(index);
return true;
}
return false;
}
}
class CartItem {
final String name;
final double price;
final int quantity;
CartItem(this.name, this.price, this.quantity);
double get totalPrice => price * quantity;
@override
String toString() => '$name x$quantity = \$${totalPrice.toStringAsFixed(2)}';
}
2.5 集合类型与泛型使用
集合类型和泛型是Dart编程的重要组成部分,提供了强大的数据处理能力。
2.5.1 List集合详解
void main() {
print("=== 集合类型演示 ===");
demonstrateListOperations();
demonstrateSetOperations();
demonstrateMapOperations();
demonstrateGenerics();
}
// List集合操作
void demonstrateListOperations() {
print("\n1. List集合操作:");
// 创建List的多种方式
List<int> numbers1 = [1, 2, 3, 4, 5];
List<int> numbers2 = List.filled(5, 0); // [0, 0, 0, 0, 0]
List<int> numbers3 = List.generate(5, (index) => index * 2); // [0, 2, 4, 6, 8]
List<String> names = <String>['Alice', 'Bob', 'Charlie'];
print("numbers1: $numbers1");
print("numbers2: $numbers2");
print("numbers3: $numbers3");
print("names: $names");
// 基本操作
numbers1.add(6); // 添加元素
numbers1.addAll([7, 8, 9]); // 添加多个元素
numbers1.insert(0, 0); // 在指定位置插入
print("修改后的numbers1: $numbers1");
// 访问和修改
print("第一个元素: ${numbers1.first}");
print("最后一个元素: ${numbers1.last}");
print("长度: ${numbers1.length}");
numbers1[1] = 99; // 修改指定位置的元素
print("修改索引1后: $numbers1");
// 查找操作
print("包含5: ${numbers1.contains(5)}");
print("99的索引: ${numbers1.indexOf(99)}");
print("大于5的第一个数: ${numbers1.firstWhere((n) => n > 5)}");
// 删除操作
numbers1.remove(99); // 删除特定值
numbers1.removeAt(0); // 删除指定索引
numbers1.removeLast(); // 删除最后一个
numbers1.removeWhere((n) => n > 7); // 删除满足条件的元素
print("删除操作后: $numbers1");
// 高级操作
List<int> doubled = numbers1.map((n) => n * 2).toList();
List<int> evenNumbers = numbers1.where((n) => n % 2 == 0).toList();
int sum = numbers1.fold(0, (previous, element) => previous + element);
print("翻倍: $doubled");
print("偶数: $evenNumbers");
print("总和: $sum");
// 排序和反转
List<int> unsorted = [3, 1, 4, 1, 5, 9, 2, 6];
print("原列表: $unsorted");
unsorted.sort(); // 升序排序
print("升序: $unsorted");
unsorted.sort((a, b) => b.compareTo(a)); // 降序排序
print("降序: $unsorted");
List<int> reversed = unsorted.reversed.toList();
print("反转: $reversed");
// 列表推导式风格操作
List<String> words = ['hello', 'world', 'dart', 'flutter'];
List<String> upperCased = [
for (String word in words)
if (word.length > 4)
word.toUpperCase()
];
print("条件转换: $upperCased");
}
// Set集合操作
void demonstrateSetOperations() {
print("\n2. Set集合操作:");
// 创建Set
Set<String> fruits = {'apple', 'banana', 'orange'};
Set<String> citrus = {'orange', 'lemon', 'lime'};
Set<int> numbers = <int>{1, 2, 3, 4, 5, 1, 2}; // 自动去重
print("水果: $fruits");
print("柑橘类: $citrus");
print("数字(去重): $numbers");
// Set操作
fruits.add('grape'); // 添加元素
fruits.addAll(['mango', 'kiwi']); // 添加多个元素
print("添加后的水果: $fruits");
// 集合运算
Set<String> union = fruits.union(citrus); // 并集
Set<String> intersection = fruits.intersection(citrus); // 交集
Set<String> difference = fruits.difference(citrus); // 差集
print("并集: $union");
print("交集: $intersection");
print("差集: $difference");
// 查询操作
print("包含apple: ${fruits.contains('apple')}");
print("是否为citrus的子集: ${{'orange', 'lemon'}.containsAll(citrus)}");
// 转换操作
List<String> fruitList = fruits.toList();
Set<int> lengths = fruits.map((f) => f.length).toSet();
print("转为列表: $fruitList");
print("长度集合: $lengths");
}
// Map集合操作
void demonstrateMapOperations() {
print("\n3. Map集合操作:");
// 创建Map
Map<String, int> ages = {
'Alice': 25,
'Bob': 30,
'Charlie': 35,
};
Map<String, String> capitals = Map<String, String>();
capitals['China'] = 'Beijing';
capitals['USA'] = 'Washington';
capitals['Japan'] = 'Tokyo';
print("年龄: $ages");
print("首都: $capitals");
// 基本操作
ages['David'] = 28; // 添加键值对
ages.putIfAbsent('Eve', () => 32); // 如果不存在则添加
print("添加后的年龄: $ages");
// 访问操作
print("Alice的年龄: ${ages['Alice']}");
print("Frank的年龄: ${ages['Frank']}"); // null
print("安全获取年龄: ${ages['Frank'] ?? 0}");
// 查询操作
print("包含Alice: ${ages.containsKey('Alice')}");
print("包含年龄30: ${ages.containsValue(30)}");
print("是否为空: ${ages.isEmpty}");
print("键: ${ages.keys}");
print("值: ${ages.values}");
// 遍历Map
print("\n遍历Map:");
ages.forEach((name, age) {
print("$name is $age years old");
});
// 高级操作
Map<String, String> ageDescriptions = ages.map(
(name, age) => MapEntry(name, age > 30 ? 'senior' : 'junior')
);
print("年龄描述: $ageDescriptions");
// 过滤操作
Map<String, int> seniors = Map.fromEntries(
ages.entries.where((entry) => entry.value > 30)
);
print("年长者: $seniors");
// 删除操作
ages.remove('Charlie');
ages.removeWhere((name, age) => age < 30);
print("删除后的年龄: $ages");
}
// 泛型详解
void demonstrateGenerics() {
print("\n4. 泛型使用:");
// 泛型类使用
Box<String> stringBox = Box<String>("Hello, Generics!");
Box<int> intBox = Box<int>(42);
print("字符串盒子: ${stringBox.value}");
print("整数盒子: ${intBox.value}");
// 泛型方法使用
List<String> strings = ["apple", "banana", "cherry"];
List<int> numbers = [1, 2, 3, 4, 5];
String firstString = getFirst<String>(strings);
int firstNumber = getFirst<int>(numbers);
print("第一个字符串: $firstString");
print("第一个数字: $firstNumber");
// 约束泛型
NumberBox<int> intNumberBox = NumberBox<int>(100);
NumberBox<double> doubleNumberBox = NumberBox<double>(3.14);
print("整数运算: ${intNumberBox.calculate()}");
print("浮点数运算: ${doubleNumberBox.calculate()}");
// 通配符和协变
List<Animal> animals = <Animal>[Dog("Buddy"), Cat("Whiskers")];
printAnimals(animals);
List<Dog> dogs = <Dog>[Dog("Max"), Dog("Luna")];
printAnimals(dogs); // 协变:List<Dog>可以赋值给List<Animal>
}
// 泛型类示例
class Box<T> {
T value;
Box(this.value);
void updateValue(T newValue) {
value = newValue;
}
T getValue() => value;
}
// 泛型方法示例
T getFirst<T>(List<T> list) {
if (list.isEmpty) {
throw ArgumentError("List cannot be empty");
}
return list.first;
}
// 约束泛型示例
class NumberBox<T extends num> {
T value;
NumberBox(this.value);
T calculate() {
return value * value as T;
}
}
// 继承和泛型
abstract class Animal {
String name;
Animal(this.name);
void makeSound();
@override
String toString() => "$runtimeType: $name";
}
class Dog extends Animal {
Dog(String name) : super(name);
@override
void makeSound() {
print("$name barks");
}
}
class Cat extends Animal {
Cat(String name) : super(name);
@override
void makeSound() {
print("$name meows");
}
}
// 协变示例
void printAnimals(List<Animal> animals) {
for (Animal animal in animals) {
print(animal);
}
}
// 实际应用:通用数据仓库
class Repository<T> {
final Map<String, T> _data = {};
void save(String id, T item) {
_data[id] = item;
}
T? findById(String id) {
return _data[id];
}
List<T> findAll() {
return _data.values.toList();
}
bool delete(String id) {
return _data.remove(id) != null;
}
void clear() {
_data.clear();
}
int get count => _data.length;
}
2.6 Dart包管理与依赖引入
包管理是Dart生态系统的重要组成部分,pubspec.yaml文件是项目配置的核心。
2.6.1 pubspec.yaml详解
# pubspec.yaml - Flutter项目配置文件
# 项目基本信息
name: flutter_demo_app # 项目名称,必须小写,可以包含下划线
description: A comprehensive Flutter demo application. # 项目描述
version: 1.2.3+4 # 版本号(语义版本+构建号)
# 环境配置
environment:
sdk: '>=3.0.0 <4.0.0' # Dart SDK版本约束
flutter: ">=3.10.0" # Flutter版本约束
# 依赖配置
dependencies:
flutter:
sdk: flutter # Flutter SDK依赖
# UI和组件
cupertino_icons: ^1.0.6 # iOS风格图标
material_design_icons_flutter: ^7.0.7296 # Material图标
# 网络请求
http: ^1.1.0 # HTTP客户端
dio: ^5.3.2 # 强大的HTTP客户端
# 状态管理
provider: ^6.0.5 # 状态管理
bloc: ^8.1.2 # BLoC模式
flutter_bloc: ^8.1.3 # Flutter BLoC
# 本地存储
shared_preferences: ^2.2.2 # 简单键值存储
sqflite: ^2.3.0 # SQLite数据库
hive: ^2.2.3 # 快速NoSQL数据库
hive_flutter: ^1.1.0
# 导航路由
go_router: ^12.1.1 # 声明式路由
# 工具类
intl: ^0.18.1 # 国际化支持
logger: ^2.0.2+1 # 日志工具
uuid: ^3.0.7 # UUID生成器
# 图片处理
cached_network_image: ^3.3.0 # 网络图片缓存
image_picker: ^1.0.4 # 图片选择器
# 权限管理
permission_handler: ^11.0.1 # 权限处理
# 设备信息
device_info_plus: ^9.1.0 # 设备信息
package_info_plus: ^4.2.0 # 应用信息
# 开发依赖(仅开发时使用)
dev_dependencies:
flutter_test:
sdk: flutter
# 代码检查和格式化
flutter_lints: ^3.0.0 # 官方代码规范
very_good_analysis: ^5.1.0 # 更严格的代码规范
# 代码生成
build_runner: ^2.4.7 # 代码生成工具
json_annotation: ^4.8.1 # JSON序列化注解
json_serializable: ^6.7.1 # JSON序列化代码生成
# 测试工具
mockito: ^5.4.2 # Mock测试
integration_test: # 集成测试
sdk: flutter
# 依赖覆盖(解决版本冲突)
dependency_overrides:
# crypto: ^3.0.3
# Flutter配置
flutter:
uses-material-design: true # 使用Material Design
# 资源文件配置
assets:
- assets/images/ # 图片资源目录
- assets/icons/ # 图标资源目录
- assets/data/ # 数据文件目录
- assets/config/config.json # 配置文件
# 字体配置
fonts:
- family: CustomFont # 自定义字体
fonts:
- asset: assets/fonts/CustomFont-Regular.ttf
- asset: assets/fonts/CustomFont-Bold.ttf
weight: 700
- asset: assets/fonts/CustomFont-Italic.ttf
style: italic
- family: IconFont # 图标字体
fonts:
- asset: assets/fonts/IconFont.ttf
# 平台特定配置
flutter:
# 生成本地化文件
generate: true
# 插件配置
plugin:
platforms:
android:
package: com.example.flutter_demo
pluginClass: FlutterDemoPlugin
ios:
pluginClass: FlutterDemoPlugin
2.6.2 包管理命令详解
// 包管理实际操作演示
void main() {
print("=== Dart包管理演示 ===");
// 这些命令在实际开发中通过终端执行
demonstratePackageCommands();
demonstratePackageUsage();
}
void demonstratePackageCommands() {
print("\n常用包管理命令:");
/*
// 基本命令
flutter pub get // 获取依赖包
flutter pub upgrade // 升级依赖包
flutter pub outdated // 查看过时的依赖
flutter pub deps // 显示依赖树
// 添加依赖
flutter pub add http // 添加运行时依赖
flutter pub add dev:build_runner // 添加开发依赖
flutter pub add --dev flutter_test // 添加开发依赖(另一种方式)
// 移除依赖
flutter pub remove http // 移除依赖
// 发布相关
flutter pub publish --dry-run // 预发布检查
flutter pub publish // 发布包到pub.dev
// 缓存管理
flutter pub cache repair // 修复缓存
flutter pub cache clean // 清理缓存
// 全局包管理
flutter pub global activate <package> // 全局激活包
flutter pub global deactivate <package> // 全局停用包
flutter pub global list // 列出全局包
*/
}
// 包使用示例
void demonstratePackageUsage() {
print("\n2. 包使用示例:");
// 在实际项目中,需要先添加依赖到pubspec.yaml
// 然后运行 flutter pub get
// 这里只是演示import语法
/*
// HTTP请求包使用
import 'package:http/http.dart' as http;
import 'package:dio/dio.dart';
// 状态管理包使用
import 'package:provider/provider.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
// 工具包使用
import 'package:intl/intl.dart';
import 'package:logger/logger.dart';
// 本地存储包使用
import 'package:shared_preferences/shared_preferences.dart';
import 'package:sqflite/sqflite.dart';
*/
}
2.6.3 实际包使用示例
// 实际项目中的包使用示例
// main.dart
import 'package:flutter/material.dart';
// import 'package:provider/provider.dart';
// import 'package:logger/logger.dart';
// import 'package:shared_preferences/shared_preferences.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Package Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: PackageDemoPage(),
);
}
}
class PackageDemoPage extends StatefulWidget {
@override
_PackageDemoPageState createState() => _PackageDemoPageState();
}
class _PackageDemoPageState extends State<PackageDemoPage> {
// final Logger logger = Logger();
String savedData = '';
@override
void initState() {
super.initState();
loadSavedData();
}
// 使用shared_preferences保存和读取数据
Future<void> loadSavedData() async {
// final prefs = await SharedPreferences.getInstance();
// setState(() {
// savedData = prefs.getString('demo_key') ?? '暂无数据';
// });
// logger.i('数据加载完成: $savedData');
}
Future<void> saveData(String data) async {
// final prefs = await SharedPreferences.getInstance();
// await prefs.setString('demo_key', data);
// logger.i('数据已保存: $data');
// loadSavedData();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('包使用演示'),
),
body: Padding(
padding: EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
'已保存的数据:',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
SizedBox(height: 8),
Container(
padding: EdgeInsets.all(12),
decoration: BoxDecoration(
border: Border.all(color: Colors.grey),
borderRadius: BorderRadius.circular(8),
),
child: Text(savedData),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () => saveData('新数据 ${DateTime.now()}'),
child: Text('保存新数据'),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () {
// 演示网络请求(需要添加http或dio依赖)
// makeNetworkRequest();
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('网络请求功能需要添加http依赖')),
);
},
child: Text('发起网络请求'),
),
],
),
),
);
}
// 网络请求示例(需要http包)
/*
Future<void> makeNetworkRequest() async {
logger.i('开始网络请求...');
try {
final response = await http.get(
Uri.parse('https://jsonplaceholder.typicode.com/posts/1')
);
if (response.statusCode == 200) {
logger.i('请求成功: ${response.body}');
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('请求成功!')),
);
} else {
logger.e('请求失败: ${response.statusCode}');
}
} catch (e) {
logger.e('网络错误: $e');
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('网络请求失败: $e')),
);
}
}
*/
}
// 自定义包结构示例
/*
项目结构:
lib/
├── main.dart
├── models/
│ ├── user.dart
│ └── product.dart
├── services/
│ ├── api_service.dart
│ ├── storage_service.dart
│ └── auth_service.dart
├── screens/
│ ├── home_screen.dart
│ ├── profile_screen.dart
│ └── login_screen.dart
├── widgets/
│ ├── custom_button.dart
│ └── loading_indicator.dart
└── utils/
├── constants.dart
├── helpers.dart
└── validators.dart
*/
// services/api_service.dart 示例
class ApiService {
// static final Dio _dio = Dio();
// static final Logger _logger = Logger();
static const String baseUrl = 'https://api.example.com';
static Future<Map<String, dynamic>> get(String endpoint) async {
try {
// final response = await _dio.get('$baseUrl$endpoint');
// _logger.i('GET $endpoint: ${response.statusCode}');
// return response.data;
// 模拟返回
return {'status': 'success', 'data': {}};
} catch (e) {
// _logger.e('API Error: $e');
throw Exception('网络请求失败: $e');
}
}
static Future<Map<String, dynamic>> post(
String endpoint,
Map<String, dynamic> data
) async {
try {
// final response = await _dio.post('$baseUrl$endpoint', data: data);
// _logger.i('POST $endpoint: ${response.statusCode}');
// return response.data;
// 模拟返回
return {'status': 'success', 'data': data};
} catch (e) {
// _logger.e('API Error: $e');
throw Exception('网络请求失败: $e');
}
}
}
// utils/constants.dart 示例
class AppConstants {
// API相关
static const String apiBaseUrl = 'https://api.example.com';
static const int apiTimeout = 30000;
// 存储键
static const String userTokenKey = 'user_token';
static const String userDataKey = 'user_data';
static const String settingsKey = 'app_settings';
// 界面相关
static const double defaultPadding = 16.0;
static const double borderRadius = 8.0;
// 颜色主题
static const Color primaryColor = Color(0xFF2196F3);
static const Color secondaryColor = Color(0xFF03DAC6);
static const Color errorColor = Color(0xFFB00020);
}
本章小结
本章深入介绍了Dart语言的核心特性:
- 语言基础:语法结构、数据类型、操作符
- 函数与类:面向对象编程、继承、多态
- 异步编程:Future、Stream、async/await模式
- 空安全:现代Dart的重要特性,提高代码安全性
- 集合与泛型:强大的数据处理能力
- 包管理:依赖管理和项目配置
练习题
-
基础语法练习
- 创建一个学生管理系统,包含Student类
- 实现添加、删除、查询学生功能
- 使用各种集合类型存储数据
-
异步编程练习
- 模拟网络请求获取用户数据
- 实现数据缓存机制
- 处理网络异常和超时
-
空安全练习
- 重构现有代码,添加空安全特性
- 使用各种空安全操作符
- 处理可空类型的转换
-
包管理练习
- 创建新的Flutter项目
- 添加常用依赖包
- 实现简单的HTTP请求和本地存储
思考问题
- Dart的异步模型与其他语言(如JavaScript)有什么异同?
- 空安全特性如何改善代码质量和开发体验?
- 在什么场景下应该使用Stream而不是Future?
- 如何在团队开发中管理和同步依赖包版本?
- 泛型在实际开发中的最佳实践是什么?