Dart 点将台 | package 包相关知识

2,988 阅读6分钟

一、Flutter 初始项目中的包

1. 如何查看项目的存在的包

AndroidStudio 中,可以在 External Libraries 下查看存在的 Dart Packages。如下是一个新建项目存在的内置包。这些包中定义的公开类、方法、对象都可以在代码中使用。其实可以看出各种 Widget 只是 Flutter 框架的一部分,除了组件之外,还有很多其他的包。这里简单讲一下相关包的功能,不详细展开了。


2. flutter 包

可以说 flutter 包是 Flutter 框架 的核心包,我们在开发中使用的绝大多数类都是这个包中的。包括 组件动画手势绘制渲染调度器


3. sky_engine 包

sky_engine 也是一个非常重要的包,内置的数据类型,int、double、bool 、List、Map 等都在 core 中。此外 async 中提供了异步相关的 FutureStreamTimer等重要类。collection 提供了集合 HashMapQueueSplayTreeSetLinkedList 等结构容器。io 提供文件操作的功能,convert 用于转换相关,ffi 用于调用 C 代码。


4.path 包

path 包中定义了很多文件路径、URL 操作的方法。也比较常用。


5.string_scanner 包

对正则的使用进行封装,可以更方便地扫描字符串,对于字符串的处理非常有价值。


二、如何创建和使用一个包

1.使用一个包

Dart 包仓库在 pub.dev/,比如我现在想使用一个 equatable 包,可以在网站上查看到最新的版本。在 项目的 pubspec.yamldependencies 节点下配置即可。

---->[pubspec.yaml]----
dependencies:
  flutter:
    sdk: flutter
  equatable: ^1.2.6 # 配置包

然后执行 Pub get ,你就可以在 Dart Packages 下看到 equatable 包。

然后通过 import 关键字就可以将包导入,在相应源码文件中使用包中定义的类。

import 'package:equatable/equatable.dart';

class Point extends Equatable{
 final double x;
 final double y;
 
 Point(this.x, this.y);

  @override
  List<Object> get props => [x,y];
}

2.如何创建一个包

比如现在我想创建一个 calculator 的包,用于一些换算逻辑的处理。在 Flutter 中通过 File -> New -> New Flutter Project... 打开创建界面,选择第三个 Flutter Package


然后填写项目的信息,如下:


这样,我们就创建好了一个包。可以在 lib 中书写代码,提供给用户使用。

library calculator;

class Calculator {

  /// 通过 [height] 身高(m) 和 [weight] 体重(kg),获取 BMI 指标
  ///
  static double getBMI(double height, double weight) {
    return weight / (height * height);
  }
}

3.如何使用自己创建的包

当你创建有个包时,就意味着你在其中敲代码时,身份是一个创造者。包里的逻辑再复杂都无所谓,你只要让用户觉得好用,简单,方便就行了。当然,每一个创造者的第一个用户都是他自己。现在回到刚才的初始项目中,这时你的角色就是 使用者。那如何使用自己创建的包呢?


使用文件路径

第一种方式是通过 通过文件路径引入包,格式如下。这种方式并不推荐,因为如果写成绝对路径,别人在运行你的项目时,就会找不到包而出现问题。

dependencies:
  flutter:
    sdk: flutter
  equatable: ^1.2.6
  
  # 通过绝对路径引入包
  calculator:
    path: /Volumes/coder/Projects/Flutter/pkg/calculator

解决方案很简单,可以将包创建在项目内,用相对路径引用。如下在 flutter_base 中创建 calculator 包,就相当于创建了一个模块,代码提交时一并提交即可。如果一个模块相对独立,这样分包的方式可以让项目结构更清晰,想要在另一个项目中复用模块的话,拷贝模块即可。这要比什么都塞在一块要好。

import 'package:calculator/calculator.dart';

Calculator.getBMI(1.8, 70)

使用 github 引入资源

如果只是自己使用,可以通过本地引用。但想要分享给别人一起使用,就需要通过网络了。可以将 calculator 包传到 github 仓库中,然后通过 git-url 进行引入,操作如下:

dependencies:
  flutter:
    sdk: flutter
  equatable: ^1.2.6

  # 通过路径引入包
  calculator:
    git:
      url: https://github.com/toly1994328/calculator.git

这样在 Dart Packages 中就会自动下载 calculator 的包,并加一个后缀名。

我们可以看到下载的包在如下文件夹下。


将包发布到 pub

使用 git 的方式,包的版本更新会比较麻烦。如果想要维护更新,最好提交到 pub 上。在此之前要做些准备,写好信息 和 LICENSE 。然后通过下面命令进行提交,第一次提交需要身份验证,这里就不展开了。

flutter packages pub publish --server=https://pub.dartlang.org


三、包相关的注意点

1. library 关键字 和 export 关键字

下面我们通过源码中的 flutter 包来看一下一些要点。下面红框中的 dart 文件在 src 包之外,其本身并没有任何的逻辑处理,只是做了包的定义相关文件的导出,分别对应 library 和 export 关键字

这样每个包可以有很多的 library。在导入包时,就不需要一次性将包中所有的文件导入,只是导入对应 library 中的文件。

import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';

这样我们也可以在 calculator 包中进行类似的处理。


2. show 关键字 和 hide 关键字

除了导出文件外,也可以导出库,但一个库中的对象非常多,如果指向导出某一部分类、方法、变量,可以使用 show 关键字,表示这些量可见。同理,如果只是某些量想要隐藏,可以使用 hide 关键字。


这两个关键字在 importexport 中都可以使用,如下 hide StatelessWidget 时,就无法在该文件中使用 StatelessWidget


3. as 关键字

通过 as 关键字可以给导入的量起别名,这样可以避免名称的冲突,或者在语义上更清晰。比如在 flutter/src/patting/borders.dart 中,引入 math ui 包时使用 as 关键字起别名。

这在使用时就可以通过 别名.量 来使用,如下 ui.lerpDouble 。 这样好处在于 lerpDouble 不会那么突然出现,让读码者知道这是 ui 包内的 lerpDouble 方法,不然可能让人认为是成员方法。


4. part 和 part of 关键字

flutter 包中,源码文件组织方式是,定义 library ,然后export 各个文件来实现。这样的话,每个份文件都是一个独立的个体,需要引入与自身相关的包。而 partpart of 则是源码文件的组织的另一种形式。vector_math 包使用的是 part 和 part of

如下,结构比较类似,也是src 外部的文件负责组织源码文件,只不过没有 export 的动作,反而是 import 一些类,然后通过 part 关键字建立与各源码文件的关系。


下面看一下源码中的 Matrix4,在一开始通过 part of 表示出它是 vector_math 中的一部分。那这有什么优势呢?


如下,在 Matrix4 中可以看到,使用了 mathquiver ,这两个名字是在 vector_math 中导入的,在 Matrix4 并未导入。可见 part of 也可将 Matrix4 视为 vector_math 中的部分,在 vector_math 中导入的包可以在子块中使用这样就可以避免每个源码文件都导入相同的东西。

到这里,关于包的几个关键字就讲完了,你应该对 Flutter 的包结构有了更深的了解。当你在使用某个对象时不妨停下想象,这个类是定义在那个包下的哪个文件中的,这样对Flutter 的理解就会更上一个层次。那本篇就到这里,谢谢观看 ~