库和可见性
使用import和library智联可以创建一个模块化的可共享的代码库。库不仅提供API,而且还是是隐私单元:以下划线(_)开头的标识符仅在库内可见。每个Dart应用程序都是一个库,即使它不适用library指令。可以使用包(packages)来分发库。
使用库
使用import来指定如何让一个库中的命名空间在另一个库中使用。
例如Dart Web应用,通常使用dart:html
库,可以像这样导入:
1
2
// 注意不要忘记分号';'
import 'dart:html';
import唯一需要的参数是指定库的URI。对于内置库,URI具有特殊的dart:
(scheme)方案。对于其他库,可以使用文件系统路径或package:
(scheme)方案。该package:方案是由包管理器(如pub工具)提供的库。
1
2
使用package管理
import 'package:test/test.dart';
- URI代表统一资源标识符。URL(统一资源定位符)是一种常见的URI。
指定库前缀
如果导入的两个具有冲突标识符的库,则可以为一个或两个库指定前缀。
1
2
3
4
5
6
7
8
9
// lib1和lib2中都含有Element类
import 'package:lib1/lib1.dart';
import 'package:lib2/lib2.dart' as lib2;
// Uses Element from lib1.
Element element1 = Element();
// Uses Element from lib2.
lib2.Element element2 = lib2.Element();
仅导入库的一部分
如果只想使用库的一部分,则可以选择行的导入库:
1
2
3
4
5
// 只导入foo
import 'package:lib1/lib1.dart' show foo;
// 导入除foo外的所有内容
import 'package:lib2/lib2.dart' hide foo;
懒加载一个库
延迟加载(懒加载)允许应用程序在需要库时按需加载库。使用懒加载的场景:
- 减少应用程序初始启动时间。
- 例如执行A/B测试-尝试(testing—trying)算法的替代实现。
- 加载很少使用的功能,例如可选的屏幕和对话框。
- 只有dart2js支持延迟加载。Flutter,Dart VM和dartdevc都不支持延迟加载。
要懒加载一个库,必须使用defferred as
来导入它。
1
2
// 懒加载一个库
import 'package:greetings/hello.dart' deferred as hello;
当使用这个库时,使用这个库的标识符来调用loadLibrary()
方法。
1
2
3
4
Future greet() async {
await hello.loadLibrary();
hello.printGreeting();
}
上面代码中,await关键字暂停执行,直到加载库。该库只加载一次,所以可以多次调用loadLibrary()而不会出现问题,async和await关键字支持异步编程,这里先不用关注它,会在介绍。
需要注意以下内容:
- 延迟库的常量不是导入文件中的常量。在加载延迟库之前,这些常量不存在。
- 不能在导入文件中使用延迟库中的类型。相反,可以考虑将接口类型移动到由延迟库和导入文件导入的库。
- Dart隐式插入loadLibrary()到您使用的deferred as namespace定义的命名空间。loadLibrary()函数返回Future。
创建库
Dart生态系统使用包来共享库和工具,该过程有点类似于使用Cocoapod创建iOS库。需要注意的几点:
- 如何组织库源代码。
- 如何使用该export指令。
- 何时使用该part指令。
- 何时使用该library指令。
下面显示了一个基本库的布局:
一个库必须有:
- pubspec 文件
pubspec file是必须的,该pubspec.yaml文件和应用程序包中的文件相同,没有特殊的名来指示包是库。
- lib 目录
库代码位于lib目录下,并且对其他包是公开的。可以根据需要在lib下创建任何层次结构。按照惯例,实现代码放在lib/src下。lib/src下的代码被认为是私有的; 其他包不需要导入src/…下的文件。要公开lib/src下的API,可以将lib/src下的文件导出到lib下的一个文件中。
如果library未指定该指令,则会根据每个库的路径和文件名生成唯一标记。因此,除非要生成库级文档,否则我们建议您省略代码中的library指令
组织库源代码
大多数情况下,每个类都应该在自己的微型库中。使用part指令可以将库拆分为多个Dart文件。但是并不推荐使用part。
直接在库根目录下创建一个主库文件,lib/
lib目录还可能包含其他非src(non-src)下的库,比如该主库依赖了其他独立的库。下面的架包提供了一种简单的方法来使用Dart创建Web服务器:
主库文件shelf.dart,如下:
1
2
3
4
5
6
7
8
9
10
export 'src/cascade.dart';
export 'src/handler.dart';
export 'src/handlers/logger.dart';
export 'src/hijack_exception.dart';
export 'src/middleware.dart';
export 'src/pipeline.dart';
export 'src/request.dart';
export 'src/response.dart';
export 'src/server.dart';
export 'src/server_handler.dart';
该架包还包含一个迷你库:shelf_io。
为了在使用dartdevc进行开发是获得最佳性能,建议将实现文件放到/lib/src
目录下,另外避免直接使用package:package_name/src/...
这种导入。
导入库文件
使用如下方式导入:
1
import 'package:utilities/utilities.dart';
当两个文件都在lib中时,或者当两个文件都在lib之外时,可以使用相对路径导入库。但是必须加上package:
.
下图显示了如何从lib和Web包中导入lib/foo/a.dart:
上图中lib包使用了相对路径来导入a.dart,此处也可以使用import 'package:my_package/foo/a.dart'
来导入。
提供其他文件
Dart官方还建议编写测试包来编写测试,将测试代码方法test包的根目录中。
如果还包含了公共配置的命令行工具( command-line tool)等,需要将它们放到bin目录下。确保能使用pub global activate来从命令行运行。然后在pubspec的executables部分中列出该工具,允许用户直接运行它而无需调用pub global run。
另外还可以在example目录下创建一个简单的示例。
在开发期间创建的非公共用途的热河工具或可执行文件都放到tool目录下。
还包含如如README和CHANGELOG等文件。
库文档
可以使用dartdoc工具,生成API文档。它使用///
语法。
1
2
3
4
/// The event handler responsible for updating the badge in the UI.
void updateBadge() {
...
}
发布开源库
可以使用pub publish来发布或更新开源库到开源网站。例如:shelf;
- 在发布程序包之前,运行dartdoc工具以确保文档生成成功并按预期显示。
- 发布包后,检查“版本”选项卡以确保成功生成文档。
- 如果文档根本没有生成,可以在“版本”选项卡中单击“失败”查看dartdoc输出。