Flutter开发环境搭建与工具链

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

  2. 解压并配置环境变量

    解压到合适目录,如:C:\flutter

    添加C:\flutter\bin到系统PATH环境变量

  3. 验证安装

    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

  2. 添加到PATH

    编辑shell配置文件(~/.zshrc 或 ~/.bash_profile)

    export PATH="$PATH:/path/to/flutter/bin"

    重新加载配置

    source ~/.zshrc

  3. 配置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

  2. 下载并安装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. 泛型在实际开发中的最佳实践是什么?
相关推荐
LSL666_1 小时前
5 Repository 层接口
android·运维·elasticsearch·jenkins·repository
alexhilton5 小时前
在Jetpack Compose中创建CRT屏幕效果
android·kotlin·android jetpack
2501_940094027 小时前
emu系列模拟器最新汉化版 安卓版 怀旧游戏模拟器全集附可运行游戏ROM
android·游戏·安卓·模拟器
下位子7 小时前
『OpenGL学习滤镜相机』- Day9: CameraX 基础集成
android·opengl
参宿四南河三9 小时前
Android Compose SideEffect(副作用)实例加倍详解
android·app
火柴就是我9 小时前
mmkv的 mmap 的理解
android
没有了遇见9 小时前
Android之直播宽高比和相机宽高比不支持后动态获取所支持的宽高比
android
shenshizhong10 小时前
揭开 kotlin 中协程的神秘面纱
android·kotlin
vivo高启强10 小时前
如何简单 hack agp 执行过程中的某个类
android
沐怡旸10 小时前
【底层机制】 Android ION内存分配器深度解析
android·面试