Flutter开发环境搭建与工具链

发布于:2025-07-25 ⋅ 阅读:(16) ⋅ 点赞:(0)

Flutter开发实战

第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

安装步骤:

  1. 下载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
  1. 解压并配置环境变量
# 解压到合适目录,如:C:\flutter
# 添加C:\flutter\bin到系统PATH环境变量
  1. 验证安装
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开发)

安装步骤:

  1. 使用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
  1. 添加到PATH
# 编辑shell配置文件(~/.zshrc 或 ~/.bash_profile)
export PATH="$PATH:/path/to/flutter/bin"

# 重新加载配置
source ~/.zshrc
  1. 配置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

安装步骤:

  1. 安装依赖
# 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
  1. 下载并安装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:

  1. 下载并安装Android Studio
  2. 启动Android Studio,完成初始设置
  3. 安装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和插件:

  1. 安装Visual Studio Code
  2. 安装必要插件
# 推荐插件列表:
# - 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真机调试:

  1. 配置开发者账号
  2. 生成证书和描述文件
  3. 在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 热重载机制原理

热重载通过以下步骤实现:

  1. 代码变更检测:监听文件系统变化
  2. 增量编译:只编译修改的代码
  3. 状态保持:保持应用当前状态
  4. 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开发环境的完整搭建过程,包括:

  1. 跨平台SDK安装:覆盖Windows、macOS、Linux三大平台
  2. IDE配置:Android Studio和VS Code的详细设置
  3. 调试环境:模拟器和真机调试的配置方法
  4. 诊断工具:Flutter Doctor的使用和问题解决
  5. 开发效率:热重载机制的原理和最佳实践

练习题

  1. 环境搭建练习

    • 在你的系统上完整安装Flutter开发环境
    • 使用Flutter Doctor检查环境配置
    • 创建并运行第一个Flutter应用
  2. 调试环境配置

    • 配置Android模拟器并运行应用
    • 如果有真机,配置真机调试环境
    • 测试热重载功能
  3. 问题排查练习

    • 故意制造环境问题(如删除PATH配置)
    • 使用本章方法进行问题排查和修复

思考问题

  1. 为什么Flutter能够实现热重载功能?其技术原理是什么?
  2. 在团队开发中,如何确保所有成员的开发环境一致?
  3. 热重载和热重启的区别是什么?什么情况下必须使用热重启?

第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语言的核心特性:

  1. 语言基础:语法结构、数据类型、操作符
  2. 函数与类:面向对象编程、继承、多态
  3. 异步编程:Future、Stream、async/await模式
  4. 空安全:现代Dart的重要特性,提高代码安全性
  5. 集合与泛型:强大的数据处理能力
  6. 包管理:依赖管理和项目配置

练习题

  1. 基础语法练习

    • 创建一个学生管理系统,包含Student类
    • 实现添加、删除、查询学生功能
    • 使用各种集合类型存储数据
  2. 异步编程练习

    • 模拟网络请求获取用户数据
    • 实现数据缓存机制
    • 处理网络异常和超时
  3. 空安全练习

    • 重构现有代码,添加空安全特性
    • 使用各种空安全操作符
    • 处理可空类型的转换
  4. 包管理练习

    • 创建新的Flutter项目
    • 添加常用依赖包
    • 实现简单的HTTP请求和本地存储

思考问题

  1. Dart的异步模型与其他语言(如JavaScript)有什么异同?
  2. 空安全特性如何改善代码质量和开发体验?
  3. 在什么场景下应该使用Stream而不是Future?
  4. 如何在团队开发中管理和同步依赖包版本?
  5. 泛型在实际开发中的最佳实践是什么?

网站公告

今日签到

点亮在社区的每一天
去签到