[Flutter]创建一个私有包并使用

在Flutter中创建一个自己的私有组件(通常称为包或库),并通过Dart的包管理工具pub进行使用。

一、创建一个新的Flutter包

1.使用命令行创建

使用Flutter命令行工具来创建一个新的包:

Dart 复制代码
$ flutter create --template=package my_private_package

这将创建一个名为my_private_package的新目录,其中包含Dart的包标准结构。

2.使用Android Studio创建

New Flutter Project -> 选择项目类型为"Package"

3.默认项目结构

默认文件和单元测试

LICENSE & CHANGELOG.md

pubspec.yaml

Dart 复制代码
name: my_private_package
description: "A new Flutter project."
version: 0.0.1
homepage:

environment:
  sdk: '>=3.3.3 <4.0.0'
  flutter: ">=1.17.0"

dependencies:
  flutter:
    sdk: flutter

dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_lints: ^3.0.0

# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec

# The following section is specific to Flutter packages.
flutter:

  # To add assets to your package, add an assets section, like this:
  # assets:
  #   - images/a_dot_burr.jpeg
  #   - images/a_dot_ham.jpeg
  #
  # For details regarding assets in packages, see
  # https://flutter.dev/assets-and-images/#from-packages
  #
  # An image asset can refer to one or more resolution-specific "variants", see
  # https://flutter.dev/assets-and-images/#resolution-aware

  # To add custom fonts to your package, add a fonts section here,
  # in this "flutter" section. Each entry in this list should have a
  # "family" key with the font family name, and a "fonts" key with a
  # list giving the asset and other descriptors for the font. For
  # example:
  # fonts:
  #   - family: Schyler
  #     fonts:
  #       - asset: fonts/Schyler-Regular.ttf
  #       - asset: fonts/Schyler-Italic.ttf
  #         style: italic
  #   - family: Trajan Pro
  #     fonts:
  #       - asset: fonts/TrajanPro.ttf
  #       - asset: fonts/TrajanPro_Bold.ttf
  #         weight: 700
  #
  # For details regarding fonts in packages, see
  # https://flutter.dev/custom-fonts/#from-packages

README.md

html 复制代码
<!--
This README describes the package. If you publish this package to pub.dev,
this README's contents appear on the landing page for your package.

For information about how to write a good package README, see the guide for
[writing package pages](https://dart.dev/guides/libraries/writing-package-pages).

For general information about developing packages, see the Dart guide for
[creating packages](https://dart.dev/guides/libraries/create-library-packages)
and the Flutter guide for
[developing packages and plugins](https://flutter.dev/developing-packages).
-->

TODO: Put a short description of the package here that helps potential users
know whether this package might be useful for them.

## Features

TODO: List what your package can do. Maybe include images, gifs, or videos.

## Getting started

TODO: List prerequisites and provide or point to information on how to
start using the package.

## Usage

TODO: Include short and useful examples for package users. Add longer examples
to `/example` folder.

```dart
const like = 'sample';
```

## Additional information

TODO: Tell users more about the package: where to find more information, how to
contribute to the package, how to file issues, what response they can expect
from the package authors, and more.

二、配置pubspec.yaml

pubspec.yaml 文件是 Dart 和 Flutter 项目的核心配置文件,用于管理项目的依赖、版本、元数据等。

具体解释参见另一文:[Flutter]配置pubspec.yaml-CSDN博客

三、开发

1.是否需要使用library 指令?

我们创建的package项目文件中,默认文件中有使用如下的library指令。下面介绍一下,这个指令到底是否必要?

Dart 复制代码
library my_private_package;

在 Flutter 或 Dart 的包开发中,关于使用 library 指令的需要并不是强制性的,而是可选的。在很多情况下,特别是在现代 Flutter 开发实践中,通常不需要显式地使用 library 指令。下面是一些关于何时以及如何使用 library 指令的指导:

(1).不使用 library 指令

对于大多数 Flutter 应用和包,你实际上不需要使用 library 指令。每个 Dart 文件默认都是一个库,即使没有显式声明。你可以直接在文件中定义类、函数和其他顶级声明,而不需要首先声明一个库。

(2).使用场景

library 指令主要用于以下几个特定场景:

  • 文档生成 :如果你希望为整个库提供文档注释,那么可以使用 library 指令来定义一个库,并在它之前添加文档注释。
  • 部分指令 :如果你需要将一个库分割成多个部分文件,你可以使用 librarypart 指令。这种情况下,主文件应该有一个 library 指令,而其他文件则使用 part of 指令。但是,这种做法在 Flutter 中较少使用,因为 importexport 通常更加方便和灵活。

示例

假设你正在创建一个包含多个部分的库,你可能会这样做:

Dart 复制代码
// lib/my_private_package.dart
library my_private_package;

part 'src/part1.dart';
part 'src/part2.dart';

// lib/src/part1.dart
part of my_private_package;

// lib/src/part2.dart
part of my_private_package;

(3).现代 Flutter 开发建议

在现代 Flutter 开发中,推荐使用 importexport 来组织和重用代码,而不是使用 librarypart。这样做的好处包括更好的封装性、更清晰的依赖管理和避免命名空间问题。

2.自定义组件

进入这个包的目录,开发你需要的功能。例如,你可以在lib目录中添加Flutter widgets、类等。

示例,创建一个的自定义组件。

Dart 复制代码
import 'package:flutter/material.dart';

class GATagetView extends StatelessWidget {
  const GATagetView({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        backgroundColor: Colors.red, // 页面的背景颜色
        resizeToAvoidBottomInset: false, // 防止键盘弹出时推动背景内容向上移动
        appBar: AppBar(
                backgroundColor: Colors.blue, // 导航栏的背景颜色
                iconTheme: const IconThemeData(
                  color: Colors.white, // 导航栏返回按钮颜色
                ),
                title: const Text(
                  "Taget",
                  style: TextStyle(
                    fontSize: 21,
                    fontWeight: FontWeight.bold,
                    color: Colors.white, // 导航栏标题文字颜色
                  ),
                ),
              ),
        body: Container(
          decoration: const BoxDecoration(
            color: Colors.white,
            // image: DecorationImage(
            //   image: AssetImage(Assets.images.iconBg.path),
            //   fit: BoxFit.cover, // 使图片铺满整个屏幕
            // ),
          ),
          child: SizedBox(
        width: double.infinity,
        height: double.infinity,
        child: SingleChildScrollView(
          child: Padding(
            padding: const EdgeInsets.all(10),
            child: Text(
              termsOfUseText(),
              textAlign: TextAlign.left,
              style: const TextStyle(
                color: Colors.black,
                fontSize: 14.0,
                fontWeight: FontWeight.normal,
                decoration: TextDecoration.none,
              ),
            ),
          ),
        ),
        ),
      )
    );
  }

  String termsOfUseText() {
    String str = """Terms of Use
    ......
    """;
    return str;
  }
}

四、测试

在 Flutter 开发中,创建和测试自定义组件是一个常见的需求。当开发私有包时,尤其是包含自定义组件的包,你会希望能够实时预览和调试这些组件。以下是一些有效的方法来预览和调试 Flutter 中的自定义组件:

1.使用示例应用

最常见的方法是在同一个项目中创建一个示例应用。这种方法很直接,也很易于设置:

  • 创建标准的 Flutter 应用 :cd到你的包的根目录,创建一个 example 文件夹,并在这个文件夹中初始化一个新的 Flutter 应用(使用 flutter create example 命令)。
bash 复制代码
$ flutter create example
  • 依赖本地包 :在示例应用的 pubspec.yaml 中添加对本地包的依赖。例如:
Dart 复制代码
dependencies:
  my_private_package:
    path: ../
  • 使用自定义组件:在示例应用中,你可以直接使用自定义包中的组件,然后运行示例应用来预览和调试这些组件。

实例:

Dart 复制代码
import 'package:my_private_package/ga_taget_view.dart';

TextButton(onPressed: (){
  Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context) {
    return const GATagetView();
  }));
}, child: const Text("跳转", style: TextStyle(color: Colors.blue),))

2.使用 Hot Reload

利用 Flutter 的 Hot Reload 功能,你可以在进行代码更改后迅速看到效果,这对于调试和迭代开发非常有用。只需在示例应用中运行你的组件,每次更改后都可以立即看到更新。

3.使用 DartPad

如果组件不依赖于任何特定的第三方包或项目特定的设置,你可以使用 DartPad 在线预览和测试 Flutter 组件。DartPad 是一个在线的 Dart 和 Flutter 编辑器,支持即时预览。

4.单元测试和组件测试

详细介绍参考:https://blog.csdn.net/wsyx768/article/details/138487007

除了视觉预览,确保组件的功能和性能符合预期是非常重要的。你可以写单元测试和组件测试(widget tests)来验证组件的行为:

  • 单元测试:测试小块的代码逻辑。

  • 组件测试 :测试 Flutter 组件的 UI 行为。使用 testWidgets 函数来模拟用户交互和检查 UI 输出。

Dart 复制代码
import 'package:flutter_test/flutter_test.dart';
import 'package:my_custom_package/my_custom_widget.dart';

void main() {
  testWidgets('My Custom Widget Test', (WidgetTester tester) async {
    await tester.pumpWidget(MyCustomWidget());

    // 进行各种断言和交互
    expect(find.text('Some Text'), findsOneWidget);
  });
}

5.使用可视化调试工具

官方使用文档:https://docs.flutter.dev/tools/devtools

仓库地址:https://github.com/flutter/devtools

版本记录:https://docs.flutter.dev/tools/devtools/release-notes

使用 Flutter 的 DevTools 进行调试。DevTools 提供了性能视图、小部件检查器、内存和网络分析工具等,可以帮助你更深入地了解你的组件和应用的运行情况。

Flutter DevTools 是一个强大的调试工具套件,它帮助开发者理解和优化他们的 Flutter 应用。DevTools 提供了多个工具来调查布局问题、性能瓶颈、内存泄漏等。以下是如何使用 Flutter DevTools 进行调试的详细步骤:

(1).启动 DevTools

首先,确保你已经安装了 Flutter 和 Dart 插件。可以通过以下步骤启动 DevTools:

Open DevTools in Web Browser:

(2).DevTools 的主要功能

DevTools 包括多个工具,每个工具都专注于不同的调试方面:

A.Inspector(检查器)
  • 用途:检查和可视化 UI 布局和树状结构。
  • 功能:可以选择任何 widget 并查看其详细属性。这对于理解和调试布局问题非常有用。
B.Timeline(时间线)
  • 用途:分析应用的帧率和性能。
  • 功能:记录并查看应用的 UI 和 GPU 线程的时间线,帮助识别帧延迟的原因。
C.Memory(内存)
  • 用途:监控和分析应用的内存使用情况。
  • 功能:查看内存图表,并进行内存快照,可以帮助找到内存泄漏。
D.Network(网络)
  • 用途:监视应用中的 HTTP 请求。
  • 功能:记录和查看发送的请求,包括请求和响应的详情,非常适合调试网络问题。
E.Performance(性能)
  • 用途:更深入地分析应用性能。
  • 功能:提供 CPU 分析器和性能图表,帮助识别热点函数和性能瓶颈。
F.Debugger(调试器)
  • 用途:逐行执行代码。
  • 功能:设置断点,查看调用堆栈,执行代码。
G.Logging(日志)
  • 用途:查看应用产生的各种日志。
  • 功能:显示 print 输出、框架日志、垃圾回收日志等。

(3).使用 DevTools 进行调试

  • 连接应用:启动 DevTools 后,你需要将其连接到正在运行的 Flutter 应用。如果是通过命令行启动,通常需要在 DevTools 的浏览器界面中输入你的应用的 URI。
  • 选择工具:根据你的调试需求,选择相应的 DevTools 工具。
  • 交互和分析:使用 DevTools 提供的功能进行交互,收集并分析数据,根据分析结果调整和优化你的代码。

五、发布

你可以选择以下几种方式来发布你的包

1.私有Git仓库

  • 将你的包推送到一个私有的Git仓库(例如GitHub, GitLab, Bitbucket等)。
  • 确保你的pubspec.yaml文件里没有敏感信息。

2.本地路径

  • 对于局部或者仅在特定项目中使用,你可以通过本地路径来依赖包。
Dart 复制代码
dependencies:
  my_private_package:
    path: ../my_private_package

3.私有Pub服务器

  • 你可以搭建一个私有的Pub服务器,但这需要额外的配置和服务器管理。

4.发布成为公开的包

发布一个公开的 Flutter 或 Dart 包主要涉及将其发布到 Dart 的包管理系统 ------ pub.dev。这是 Dart 和 Flutter 社区的中央包仓库,类似于 Node.js 的 npm 或 Python 的 PyPI。下面是发布公开包的基本步骤:

(1).准备你的包

首先,确保你的包满足以下基本要求:

  • pubspec.yaml: 包含所有必要信息,如版本号、描述、依赖等。
  • README.md: 描述包的用途、安装方法、如何使用等。
  • CHANGELOG.md: 记录包的每个版本的变更。
  • LICENSE: 包含开源许可证的文件(例如 MIT、BSD、Apache 等)。

确保代码质量良好,有适当的注释和文档,同时最好有单元测试。

(2).检查包的健康状况

使用 Dart 的 pub 工具来分析你的包,确保没有警告或错误:

Dart 复制代码
$ dart pub publish --dry-run

这个命令会执行一个预发布检查,不会真正发布包,但会告诉你是否有什么问题需要解决。

使用publish命令时,需要先将publish_to配置移除。

Dart 复制代码
name: flutter_test_application
description: "A new Flutter project."

# 以下行可防止包被意外发布到
# pub.dev 使用 `flutter pub publish`。 这是私有包的首选。
publish_to: 'none' # 如果您想发布到 pub.dev,请删除此行

(3).发布包

一旦你的包准备好并通过了预检,你可以使用以下命令来发布它:

Dart 复制代码
$ dart pub publish

在执行这个命令时,将会要求你登录到你的 Google 账户(如果还没有登录的话),因为 pub.dev 使用 Google 账户进行身份验证。

(4).管理和维护

一旦你的包发布到 pub.dev,你需要对它进行管理和维护。这包括处理用户的问题、修复 bug、更新文档和发布新版本。

确保遵循语义版本控制规则更新你的包版本。当你做出修改并希望发布新版本时,你需要更新 pubspec.yaml 文件中的版本号,更新 CHANGELOG.md 文件,然后再次运行 dart pub publish

六、在项目中使用你的包

在其他Flutter项目中,你可以通过以下方式之一添加依赖:

1.Git依赖

pubspec.yaml中添加依赖后,运行**$ flutter pub get**来安装包。

php 复制代码
dependencies:
  my_private_package:
    git:
      url: git@github.com:yourusername/my_private_package.git
      ref: master
      # ref: v1.0.0
      # ref: abc1234

这种方式是从一个 Git 仓库导入依赖,ref 参数可以是一个分支名、标签或者具体的提交哈希。

版本管理

  • 分支名 : 指定为 master,意味着每次 pub getflutter pub get 都会检查 master 分支的最新状态。
  • 标签 : 如果你想管理版本,最佳实践是使用 Git 标签。你可以在 Git 仓库中为每个稳定版本创建一个标签,然后在 ref 中指定这个标签。
  • 提交哈希: 对于最精确的版本控制,你可以指定一个具体的提交哈希。这确保了无论何时拉取代码,依赖都是完全相同的。

使用实例:

Dart 复制代码
import 'package:my_private_package/ga_taget_view.dart';

TextButton(onPressed: (){
  Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context) {
    return const GATagetView();
  }));
}, child: const Text("跳转", style: TextStyle(color: Colors.blue),))

2.路径依赖(如果包在本地)

在项目的pubspec.yaml中添加了依赖,运行**$ flutter pub get**来安装包。

(1).使用绝对路径

你需要根据你的系统环境确定完整的路径。例如,如果你的用户目录是 /Users/yourusername,则配置应如下所示:

Dart 复制代码
dependencies:
  my_private_package:
    path: /Users/yourusername/documents/my_private_package

(2).使用相对路径

如果你的私有包位于与你的 Flutter 项目相对较近的位置,你也可以使用相对路径。例如,如果你的 Flutter 项目和 my_private_package 都在同一个父目录下,你可以这样配置:

Dart 复制代码
dependencies:
  my_private_package:
    path: ../my_private_package

注意: 不能使用~/documents/my_private_package这种格式来指代目录。虽然 ~ 在许多命令行环境中通用(指代用户的主目录),但在 pubspec.yaml 文件中,Flutter 不解析 ~ 为主目录。

之后,你就可以在你的Flutter应用中导入并使用这个包了。

Dart 复制代码
import 'package:my_private_package/ga_taget_view.dart';

TextButton(onPressed: (){
  Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context) {
    return const GATagetView();
  }));
}, child: const Text("跳转", style: TextStyle(color: Colors.blue),))
相关推荐
AiFlutter9 小时前
Flutter之Package教程
flutter
Mingyueyixi13 小时前
Flutter Spacer引发的The ParentDataWidget Expanded(flex: 1) 惨案
前端·flutter
crasowas1 天前
Flutter问题记录 - 适配Xcode 16和iOS 18
flutter·ios·xcode
老田低代码2 天前
Dart自从引入null check后写Flutter App总有一种难受的感觉
前端·flutter
AiFlutter2 天前
Flutter Web首次加载时添加动画
前端·flutter
ZemanZhang4 天前
Flutter启动无法运行热重载
flutter
AiFlutter4 天前
Flutter-底部选择弹窗(showModalBottomSheet)
flutter
帅次4 天前
Android Studio:驱动高效开发的全方位智能平台
android·ide·flutter·kotlin·gradle·android studio·android jetpack
程序者王大川4 天前
【前端】Flutter vs uni-app:性能对比分析
前端·flutter·uni-app·安卓·全栈·性能分析·原生
yang2952423614 天前
使用 Vue.js 将数据对象的值放入另一个数据对象中
前端·vue.js·flutter