第2章:第一个Flutter应用 —— 2.5 包管理

78 阅读5分钟

2.5 包管理

📚 核心知识点

  1. 包(Package)的概念
  2. pubspec.yaml 配置文件
  3. Pub 仓库(pub.dev)
  4. 添加和使用第三方包
  5. 不同的依赖方式

💡 核心概念

什么是包(Package)?

包(Package) 是一个可复用的代码模块,类似于:

  • Java 的 jar
  • Android 的 aar
  • Web 的 npm
  • iOS 的 CocoaPods

为什么需要包管理?

flowchart LR
    A["开发者A<br/>写了日期处理工具"] --> B["发布到 pub.dev"]
    C["开发者B"] --> D["在 pubspec.yaml<br/>添加依赖"]
    D --> E["flutter pub get<br/>下载包"]
    E --> F["在代码中使用"]
    
    B -.-> D
    
    style B fill:#C8E6C9
    style F fill:#BBDEFB

好处:

  • ✅ 代码复用,避免重复造轮子
  • ✅ 统一管理版本
  • ✅ 提高开发效率
  • ✅ 社区共享

📝 pubspec.yaml 配置文件

文件结构

name: flutter_application_1        # 应用名称
description: A Flutter project     # 应用描述
version: 1.0.0                     # 版本号

environment:
  sdk: '>=3.0.0 <4.0.0'            # Dart SDK 版本

dependencies:                       # 应用依赖的包
  flutter:
    sdk: flutter
  cupertino_icons: ^1.0.0          # iOS 风格图标
  english_words: ^4.0.0            # 英文单词包

dev_dependencies:                   # 开发工具依赖
  flutter_test:
    sdk: flutter
  flutter_lints: ^2.0.0            # 代码检查工具

flutter:                            # Flutter 相关配置
  uses-material-design: true       # 使用 Material Design

字段说明

字段说明示例
name包/应用名称my_app
description描述信息A new Flutter project
version版本号1.0.0+1
dependencies应用依赖的包english_words: ^4.0.0
dev_dependencies开发工具依赖flutter_test: ...
flutterFlutter 配置uses-material-design: true

dependencies vs dev_dependencies

flowchart TB
    subgraph "dependencies(生产依赖)"
        A1["参与编译"]
        A2["打包到APK/IPA"]
        A3["用户设备上运行"]
    end
    
    subgraph "dev_dependencies(开发依赖)"
        B1["仅开发时使用"]
        B2["不打包到APK/IPA"]
        B3["测试工具、代码生成等"]
    end
    
    style A2 fill:#FFCDD2
    style B2 fill:#C8E6C9

🌐 Pub 仓库

什么是 Pub?

Pub (pub.dev) 是 Google 官方的 Dart/Flutter 包仓库。

如何查找包?

  1. 访问 pub.dev
  2. 搜索包名(如:english_words
  3. 查看包信息:
    • 版本号
    • 是否支持 Flutter
    • 文档和示例
    • 评分和流行度

包的评分指标

指标说明
Likes点赞数(受欢迎程度)
Pub Points质量评分(最高130分)
Popularity使用率
✓ Flutter FavoriteFlutter 官方推荐

🎯 使用第三方包:english_words

步骤1:添加依赖

编辑 pubspec.yaml

dependencies:
  flutter:
    sdk: flutter
  english_words: ^4.0.0  # 添加这一行

版本约束说明:

  • ^4.0.0 - 兼容 4.0.0 到 5.0.0 之前的版本
  • >=4.0.0 <5.0.0 - 显式指定范围
  • 4.0.0 - 精确版本

步骤2:下载包

方法1: 点击 Android Studio/VS Code 右上角的 "Pub get" 按钮

方法2: 命令行执行

flutter pub get

输出:

Running "flutter pub get" in flutter_application_1...
Process finished with exit code 0

步骤3:导入包

import 'package:english_words/english_words.dart';

步骤4:使用包

class RandomWordsWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // 生成随机英文单词对
    final wordPair = WordPair.random();
    
    return Text(
      wordPair.asPascalCase,  // 帕斯卡命名:HelloWorld
      style: TextStyle(fontSize: 24),
    );
  }
}

english_words 功能展示

final word = WordPair.random();

print(word.asPascalCase);   // HelloWorld
print(word.asCamelCase);    // helloWorld
print(word.asSnakeCase);    // hello_world
print(word.asLowerCase);    // hello world
print(word.asUpperCase);    // HELLO WORLD

📦 不同的依赖方式

1. 依赖 Pub 仓库(推荐)

dependencies:
  http: ^1.0.0
  provider: ^6.0.0

优点: 版本管理方便,自动处理依赖冲突


2. 依赖本地包

场景: 正在开发自己的包,还未发布

dependencies:
  my_package:
    path: ../my_package  # 相对路径

dependencies:
  my_package:
    path: /Users/username/projects/my_package  # 绝对路径

目录结构:

workspace/
├── my_app/              # 主应用
│   └── pubspec.yaml     # 依赖 my_package
└── my_package/          # 本地包
    └── pubspec.yaml

3. 依赖 Git 仓库

场景: 使用未发布到 pub.dev 的包,或使用特定分支

基本用法(包在仓库根目录)

dependencies:
  my_package:
    git:
      url: https://github.com/username/my_package.git

指定分支

dependencies:
  my_package:
    git:
      url: https://github.com/username/my_package.git
      ref: develop  # 分支名

指定路径(包在子目录)

dependencies:
  package1:
    git:
      url: https://github.com/flutter/packages.git
      path: packages/package1  # 子目录路径

指定 Tag 或 Commit

dependencies:
  my_package:
    git:
      url: https://github.com/username/my_package.git
      ref: v1.0.0  # Tag
      # 或
      ref: abc1234  # Commit SHA

🔄 包管理命令

常用命令

命令说明
flutter pub get下载依赖包
flutter pub upgrade升级所有依赖包到最新版本
flutter pub outdated检查过期的依赖
flutter pub deps查看依赖树
flutter pub cache repair修复包缓存

命令详解

1. flutter pub get

flutter pub get

作用: 根据 pubspec.yaml 下载依赖

生成: pubspec.lock 文件(锁定具体版本)

2. flutter pub upgrade

flutter pub upgrade

作用: 升级所有包到最新兼容版本

示例:

english_words: ^4.0.0  →  升级到 4.0.5(最新)

3. flutter pub outdated

flutter pub outdated

输出:

Package Name    Current  Upgradable  Resolvable  Latest
english_words   4.0.0    4.0.5       4.0.5       4.1.0
http            0.13.5   0.13.6      1.0.0       1.0.0

📊 依赖方式对比

flowchart TB
    Start["选择依赖方式"]
    
    Q1{"包是否在<br/>pub.dev?"}
    Q2{"是否正在<br/>开发这个包?"}
    Q3{"包是否在<br/>GitHub等?"}
    
    A1["✅ pub.dev 依赖<br/>dependencies:<br/>  pkg: ^1.0.0"]
    A2["✅ 本地依赖<br/>dependencies:<br/>  pkg:<br/>    path: ../pkg"]
    A3["✅ Git 依赖<br/>dependencies:<br/>  pkg:<br/>    git:<br/>      url: ..."]
    
    Start --> Q1
    Q1 -->|"是"| A1
    Q1 -->|"否"| Q2
    Q2 -->|"是"| A2
    Q2 -->|"否"| Q3
    Q3 -->|"是"| A3
    
    style A1 fill:#C8E6C9
    style A2 fill:#FFF9C4
    style A3 fill:#BBDEFB

🎯 最佳实践

1. 版本管理

推荐: 使用版本约束

dependencies:
  http: ^1.0.0        # ✅ 允许小版本更新
  provider: '>=6.0.0 <7.0.0'  # ✅ 显式范围

不推荐: 使用 any 或不指定版本

dependencies:
  http: any  # ❌ 可能导致版本冲突

2. 定期更新依赖

# 检查过期的包
flutter pub outdated

# 升级包
flutter pub upgrade

3. 提交 pubspec.lock

提交到版本控制

原因: 确保团队成员使用相同版本的依赖

4. 清理无用依赖

定期检查 pubspec.yaml,删除不再使用的包。


📝 常见问题

Q1: 为什么要有 pubspec.lock 文件?

A: pubspec.lock 锁定了具体版本,确保:

  • 团队成员使用相同版本
  • CI/CD 构建一致性
  • 避免意外升级导致的问题

对比:

# pubspec.yaml (约束)
dependencies:
  http: ^1.0.0  # 允许 1.0.0 到 2.0.0

# pubspec.lock (具体版本)
packages:
  http:
    version: "1.0.5"  # 锁定具体版本

Q2: pub get 和 pub upgrade 的区别?

命令行为
pub get根据 pubspec.lock 下载,没有则解析 pubspec.yaml
pub upgrade忽略 pubspec.lock,下载最新兼容版本

Q3: 如何解决版本冲突?

场景: 两个包依赖同一个包的不同版本

你的应用  package_a: ^1.0.0  http: ^0.13.0
          package_b: ^2.0.0  http: ^1.0.0
 冲突!

解决方案:

  1. 升级冲突的包
dependency_overrides:
  http: ^1.0.0  # 强制使用指定版本
  1. 联系包作者更新依赖

  2. 等待包更新或切换到其他包

Q4: 本地依赖的路径找不到?

错误:

Could not find a file named "pubspec.yaml" in ...

解决:

  • 检查路径是否正确
  • 使用绝对路径测试
  • 确保目标目录有 pubspec.yaml

Q5: Git 依赖下载很慢?

解决方案:

  1. 使用国内镜像
# 设置环境变量
export PUB_HOSTED_URL=https://pub.flutter-io.cn
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
  1. 使用 SSH 代替 HTTPS
dependencies:
  my_package:
    git:
      url: git@github.com:username/my_package.git  # SSH

🎓 跟着做练习

练习1:添加并使用 intl 包 ⭐⭐

目标: 学习日期格式化

步骤:

  1. 添加依赖到 pubspec.yaml
dependencies:
  intl: ^0.18.0
  1. 下载包
flutter pub get
  1. 使用 intl 格式化日期
import 'package:intl/intl.dart';

class DateFormatExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final now = DateTime.now();
    
    // 格式化日期
    final formatter1 = DateFormat('yyyy-MM-dd HH:mm:ss');
    final formatter2 = DateFormat('yyyy年MM月dd日');
    final formatter3 = DateFormat.yMMMd('zh_CN');
    
    return Column(
      children: [
        Text('格式1: ${formatter1.format(now)}'),
        Text('格式2: ${formatter2.format(now)}'),
        Text('格式3: ${formatter3.format(now)}'),
      ],
    );
  }
}

预期输出:

格式1: 2024-01-15 14:30:25
格式2: 2024年01月15日
格式3: 2024年1月15日

练习2:添加并使用 uuid 包 ⭐⭐

目标: 生成唯一ID

步骤:

  1. 添加依赖
dependencies:
  uuid: ^4.0.0
  1. 生成 UUID
import 'package:uuid/uuid.dart';

class UuidExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var uuid = const Uuid();
    
    return Column(
      children: [
        Text('UUID v1: ${uuid.v1()}'),
        Text('UUID v4: ${uuid.v4()}'),
        Text('UUID v5: ${uuid.v5(Uuid.NAMESPACE_URL, 'flutter.dev')}'),
      ],
    );
  }
}

预期输出:

UUID v1: 550e8400-e29b-41d4-a716-446655440000
UUID v4: 6ba7b810-9dad-11d1-80b4-00c04fd430c8
UUID v5: 3d813cbb-47fb-32ba-91df-831e1593ac29

参考: 《Flutter实战·第二版》2.5节