> 技术文档 > Flutter开发实战之环境搭建与工具链_flutter 环境搭建

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

常见问题解决:

# 问题:\'flutter\' 不是内部或外部命令# 解决:检查PATH环境变量是否正确添加Flutter的bin目录# 问题:网络连接问题# 解决:配置镜像源export PUB_HOSTED_URL=https://pub.flutter-io.cnexport 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)\"# 安装Flutterbrew install --cask flutter# 或者手动下载curl -O https://storage.googleapis.com/flutter_infra_release/releases/stable/macos/flutter_macos_3.16.0-stable.zipunzip 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/Debiansudo apt-get updatesudo apt-get install curl git unzip xz-utils zip libglu1-mesa# CentOS/RHELsudo yum install curl git unzip xz zip mesa-libGLU
  1. 下载并安装Flutter
# 下载Flutterwget 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# 添加到PATHexport 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添加// 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 acceptedflutter doctor --android-licenses# 按提示接受所有许可证# 问题2:Xcode not configuredsudo xcode-select -s /Applications/Xcode.app/Contents/Developersudo xcodebuild -license accept# 问题3:Flutter SDK版本过旧flutter upgrade# 问题4:Dart SDK version不匹配flutter channel stableflutter 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 { 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: [ 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 { @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 { // 将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:8080export HTTPS_PROXY=http://proxy.example.com:8080# 解决方案3:使用国内镜像export PUB_HOSTED_URL=https://pub.flutter-io.cnexport FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
1.7.2 权限相关问题
# Android权限问题# 在android/app/src/main/AndroidManifest.xml中添加权限# iOS权限问题# 在ios/Runner/Info.plist中添加权限说明NSCameraUsageDescriptionThis app needs camera access to take photos
1.7.3 构建错误解决
// 常见错误1:版本冲突// pubspec.yamldependencies: flutter: sdk: flutter some_package: ^2.0.0 # 确保版本兼容// 解决方案flutter pub deps // 查看依赖树flutter pub upgrade // 升级依赖flutter clean // 清理构建缓存flutter pub get // 重新获取依赖// 常见错误2:Gradle构建失败// android/build.gradlebuildscript { 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 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}\"); // 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 = [] ..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  _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 processNumbers(List numbers, int Function(int) processor) { return numbers.map(processor).toList();}// 6. 闭包Function createMultiplier(int factor) { return (int value) => value * factor;}// 7. 生成器函数Iterable naturalNumbers(int max) sync* { int current = 1; while (current <= max) { yield current++; }}// 8. 异步生成器函数Stream asynchronousNaturals(int max) async* { int current = 1; while (current  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 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\"); }}// 使用mixinclass 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 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 immediateFuture = Future.value(\"立即返回的值\"); String result = await immediateFuture; print(\"立即结果: $result\"); // 方式4: 延迟Future print(\"开始延迟操作...\"); await Future.delayed(Duration(seconds: 1), () { print(\"延迟操作完成!\"); });}// 模拟异步获取用户数据Future fetchUserData(int userId) async { // 模拟网络延迟 await Future.delayed(Duration(milliseconds: 500)); // 模拟随机失败 if (Random().nextBool()) { throw Exception(\"网络错误: 无法获取用户 $userId 的数据\"); } return \"User$userId{name: \'张三\', age: 25}\";}// Future错误处理Future 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 demonstrateFutureCombination() async { print(\"\\n3. Future组合操作:\"); // 并行执行多个Future List<Future> futures = [ fetchData(\"API1\", 300), fetchData(\"API2\", 500), fetchData(\"API3\", 200), ]; // 等待所有Future完成 try { List 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 fetchData(String source, int delay) async { await Future.delayed(Duration(milliseconds: delay)); if (Random().nextDouble() < 0.2) { // 20%失败率 throw Exception(\"$source 请求失败\"); } return \"$source 的数据\";}Future processData(String data) async { await Future.delayed(Duration(milliseconds: 100)); return \"处理后的 $data\";}Future 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 demonstrateStreamBasics() async { print(\"\\n1. Stream基础操作:\"); // 创建简单的Stream Stream 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 demonstrateStreamTransformation() async { print(\"\\n2. Stream变换和过滤:\"); // 创建数字流 Stream 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\"));}// 自定义StreamFuture demonstrateCustomStream() async { print(\"\\n3. 自定义Stream:\"); // 使用async*创建Stream await for (String data in generateDataStream()) { print(\"自定义Stream数据: $data\"); }}// 生成器函数创建StreamStream generateDataStream() async* { for (int i = 1; i <= 5; i++) { await Future.delayed(Duration(milliseconds: 300)); yield \"数据项 $i\"; if (i == 3) { yield* generateSubStream(); // 委托给另一个Stream } }}Stream generateSubStream() async* { yield \"子流数据 A\"; yield \"子流数据 B\";}// StreamController使用Future demonstrateStreamController() async { print(\"\\n4. StreamController使用:\"); // 创建StreamController StreamController controller = StreamController(); // 监听Stream StreamSubscription 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>? _controller; // 获取实时数据流 static Stream<Map> get realTimeData { _controller ??= StreamController<Map>.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? nullableList; // 1. 空感知访问操作符 (?.) print(\"安全访问长度: ${nullableString?.length}\"); // 输出: null print(\"安全访问第一个元素: ${nullableList?.first}\"); // 输出: null // 2. 空合并操作符 (??) String result = nullableString ?? \"默认值\"; print(\"空合并结果: $result\"); // 输出: 默认值 // 3. 空合并赋值操作符 (??=) nullableString ??= \"赋值的默认值\"; print(\"空合并赋值: $nullableString\"); // 输出: 赋值的默认值 // 4. 级联空感知操作符 (?..) List? optionalList = [\"item1\", \"item2\"]; optionalList?..add(\"item3\")..add(\"item4\"); print(\"级联操作结果: $optionalList\"); // 5. 空感知索引操作符 (?[]) List? 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 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 _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 && index  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 numbers1 = [1, 2, 3, 4, 5]; List numbers2 = List.filled(5, 0); // [0, 0, 0, 0, 0] List numbers3 = List.generate(5, (index) => index * 2); // [0, 2, 4, 6, 8] List names = [\'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 doubled = numbers1.map((n) => n * 2).toList(); List evenNumbers = numbers1.where((n) => n % 2 == 0).toList(); int sum = numbers1.fold(0, (previous, element) => previous + element); print(\"翻倍: $doubled\"); print(\"偶数: $evenNumbers\"); print(\"总和: $sum\"); // 排序和反转 List 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 reversed = unsorted.reversed.toList(); print(\"反转: $reversed\"); // 列表推导式风格操作 List words = [\'hello\', \'world\', \'dart\', \'flutter\']; List upperCased = [ for (String word in words) if (word.length > 4) word.toUpperCase() ]; print(\"条件转换: $upperCased\");}// Set集合操作void demonstrateSetOperations() { print(\"\\n2. Set集合操作:\"); // 创建Set Set fruits = {\'apple\', \'banana\', \'orange\'}; Set citrus = {\'orange\', \'lemon\', \'lime\'}; Set numbers = {1, 2, 3, 4, 5, 1, 2}; // 自动去重 print(\"水果: $fruits\"); print(\"柑橘类: $citrus\"); print(\"数字(去重): $numbers\"); // Set操作 fruits.add(\'grape\');  // 添加元素 fruits.addAll([\'mango\', \'kiwi\']); // 添加多个元素 print(\"添加后的水果: $fruits\"); // 集合运算 Set union = fruits.union(citrus); // 并集 Set intersection = fruits.intersection(citrus); // 交集 Set difference = fruits.difference(citrus); // 差集 print(\"并集: $union\"); print(\"交集: $intersection\"); print(\"差集: $difference\"); // 查询操作 print(\"包含apple: ${fruits.contains(\'apple\')}\"); print(\"是否为citrus的子集: ${{\'orange\', \'lemon\'}.containsAll(citrus)}\"); // 转换操作 List fruitList = fruits.toList(); Set lengths = fruits.map((f) => f.length).toSet(); print(\"转为列表: $fruitList\"); print(\"长度集合: $lengths\");}// Map集合操作void demonstrateMapOperations() { print(\"\\n3. Map集合操作:\"); // 创建Map Map ages = { \'Alice\': 25, \'Bob\': 30, \'Charlie\': 35, }; Map capitals = Map(); 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 ageDescriptions = ages.map( (name, age) => MapEntry(name, age > 30 ? \'senior\' : \'junior\') ); print(\"年龄描述: $ageDescriptions\"); // 过滤操作 Map 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 stringBox = Box(\"Hello, Generics!\"); Box intBox = Box(42); print(\"字符串盒子: ${stringBox.value}\"); print(\"整数盒子: ${intBox.value}\"); // 泛型方法使用 List strings = [\"apple\", \"banana\", \"cherry\"]; List numbers = [1, 2, 3, 4, 5]; String firstString = getFirst(strings); int firstNumber = getFirst(numbers); print(\"第一个字符串: $firstString\"); print(\"第一个数字: $firstNumber\"); // 约束泛型 NumberBox intNumberBox = NumberBox(100); NumberBox doubleNumberBox = NumberBox(3.14); print(\"整数运算: ${intNumberBox.calculate()}\"); print(\"浮点数运算: ${doubleNumberBox.calculate()}\"); // 通配符和协变 List animals = [Dog(\"Buddy\"), Cat(\"Whiskers\")]; printAnimals(animals); List dogs = [Dog(\"Max\"), Dog(\"Luna\")]; printAnimals(dogs); // 协变:List可以赋值给List}// 泛型类示例class Box { T value; Box(this.value); void updateValue(T newValue) { value = newValue; } T getValue() => value;}// 泛型方法示例T getFirst(List list) { if (list.isEmpty) { throw ArgumentError(\"List cannot be empty\"); } return list.first;}// 约束泛型示例class NumberBox { 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 animals) { for (Animal animal in animals) { print(animal); }}// 实际应用:通用数据仓库class Repository { final Map _data = {}; void save(String id, T item) { _data[id] = item; } T? findById(String id) { return _data[id]; } List 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 =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  // 全局激活包 flutter pub global deactivate  // 全局停用包 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.dartimport \'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 { // final Logger logger = Logger(); String savedData = \'\'; @override void initState() { super.initState(); loadSavedData(); } // 使用shared_preferences保存和读取数据 Future loadSavedData() async { // final prefs = await SharedPreferences.getInstance(); // setState(() { // savedData = prefs.getString(\'demo_key\') ?? \'暂无数据\'; // }); // logger.i(\'数据加载完成: $savedData\'); } Future 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 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> 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> post( String endpoint, Map 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. 泛型在实际开发中的最佳实践是什么?