Dart基础之 库(libraries)和可见性(visibility)

2,652 阅读8分钟

前言

importlibrary指令可以帮助你创建模块化且可共享的代码库。 库(library)不仅提供API,而且是隐私的单元:以下划线(_)开头的标识符仅在库内部可见。 每个Dart应用程序都是一个库,即使它不使用library指令。

库可以使用分发。

使用库

使用import指定一个库的命名空间在另外一个库的范围中使用。

例如,Dart Web应用程序通常使用dart:html库,可以像这样导入:

import 'dart:html';

import的唯一必需参数是指定库的URI。 对于内置库,URI具有特殊的dart:scheme。 对于其他库,可以使用文件系统路径或package:schemepackage:scheme指定的库由包管理器(例如pub工具)提供。 例如:

import 'package:test/test.dart';

注意:URI代表统一资源标识符。 URL(统一资源定位符)是一种常见的URI。

指定一个库的前缀

如果你导入两个库,这两个库冲突了,那么可以为一个或两个库指定一个前缀。 例如,如果library1和library2都具有Element类,那么你可能使用以下代码:

import 'package:lib1/lib1.dart';
import 'package:lib2/lib2.dart' as lib2;

// 使用 lib1 中的 Element 
Element element1 = Element();

// 使用 lib2 中的 Element 
lib2.Element element2 = lib2.Element();

只导入库的一部分

如果你只用到了库的一部分,你可以选择性的导入,例如:

// 只导入 foo
import 'package:lib1/lib1.dart' show foo;

// 除了 foo 其他都导入
import 'package:lib2/lib2.dart' hide foo;

延迟加载一个库

延迟加载(也称为懒加载 lazy loading)可以允许一个 web app 当用到库的时候才去加载。以下是一些可能用到延迟加载的情况:

  • 减少一个 web app 的初始化启动时间
  • 做 A/B testing - 一个尝试可替代方案的算法
  • 加载很难用到的函数,例如可选的 screens 和 dialogs

仅dart2js支持延迟加载。 Flutter,Dart VM和dartdevc不支持延迟加载。 有关更多信息,请参见问题#33118和问题#27776

延迟加载一个库,你必须在第一次导入的时候用 deferred as

import 'package:greetings/hello.dart' deferred as hello;

当你需要该库时,调用loadLibrary()来使用库的标识符。

Future greet() async {
  await hello.loadLibrary();
  hello.printGreeting();
}

在前面的代码中,关键词await会暂停执行直到库被加载好。

你可以调用loadLibray()多次加载一个库,但这个库只会被加载一次。

当你使用延迟加载时,请记住:

  • 在导入文件过程中,一个延迟加载库的常量不是常量了。记住,这些常量不会存在直到延迟库加载好。
  • 在导入文件过程中,你不能使用延迟库中的类型。所以考虑把接口类型移到一个库中,同时导入它和延迟库。
  • Dart 隐式插入loadLibrary()到你定义使用deferred as namespace的命名空间。loadLibrary()函数返回一个 Future

实现一个库

Dart生态系统使用包来共享软件,例如库和工具。 该页面告诉你如何创建一个包,重点介绍最常见的包,库包(library package)。

一个库包由什么组成

下面的演示图展示了一个最简单的库包的结构:

一个库包最少需要:

pubspec 文件 pubspec.yaml文件对于一个库和一个应用包来说都是相同的--没有特殊的设计来区分一个包是一个库。

lib 目录 就像你想的,lib 目录下放的是这个库的代码,并且对于其他包是公开的。你可以在 lib 目录下创建任何层级。为了方便,实现的代码是放在 lib/src下的。在 lib/src下的代码可以考虑设置成私有的;其他包不需要导入 src/...。为了让你在 lib/src 下的 APIs 公开, 你可以从一个直接在 lib 目录下的文件中导出lib/src下的文件。

注意:未指定library指令时,会根据每个库的路径和文件名为它们生成一个唯一标记。 因此,我们建议你从代码中省略library指令,除非你打算生成库级文档

组织一个库包

创建小型的单个库(称为迷你库)时,库包最容易维护,扩展和测试。 在大多数情况下,每个类都应位于自己的微型库中,除非你遇到两个类紧密耦合的情况。

注意:你可能听说过part指令,该指令可将库拆分为多个Dart文件。 我们建议你避免使用part而是创建小型库。

在lib, lib/.dart下直接创建一个main库文件,该文件将导出所有公共API。 这使用户可以通过导入单个文件来获得库的所有功能。

lib目录可能还包括其他可导入的非src库。 例如,也许你的主库跨平台工作,但是你创建了依赖dart:io或dart:html的单独的库。 某些软件包具有单独的库,但如果没有主库,则应使用前缀导入。

让我们看一下现实世界中库包的结构:shelf。 shelf包提供了一种使用Dart创建Web服务器的简便方法,并以Dart库包常用的结构进行布局:

直接在lib下,主库文件,shelf.dart,从lib/src导出几个文件:

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包也包含了一个mini 库:shelf_io。这个适配器处理了从 dart:io 中的 HttpRequest 对象。

Web应用程序提示:为了在使用dartdevc开发时获得最佳性能,请将实现文件放在/lib/src下,而不是在/lib下的其他地方。 另外,避免导入package:package_name/src/....

导入库文件

当你导入一个库文件时,可以使用package:直接指定它的 URI

import 'package:utilities/utilities.dart';

无论文件是不是在 lib 目录内外,你都可以用相对路径导入一个库,但是你必须使用package:。当你有疑问的时候,直接使用package:指令在所有情况下都管用。

下图显示了如何从lib和web导入lib/foo/a.dart

注意:尽管lib图形使用相对导入(import'../foo/a.dart')显示lib/bar/b.dart,但它可以改用package:指令(import'package:my_package/foo/ a.dart')。

提供额外的文件

设计良好的库包易于测试。 我们建议你使用test包编写测试,并将测试代码放在包顶部的test目录中。

如果你创建任何供公众使用的命令行工具,请将其放置在bin目录中,该目录是公共的。 使用pub global activate启用从命令行运行工具的功能。 在pubspec的可执行文件部分列出该工具后,用户无需调用pub global run就可以直接运行它。

提供一个如何使用你的库的例子会非常有用。 可以放在包的顶级目录example中。

你在开发过程中创建的任何非公共使用的工具或可执行文件都可以放入tool目录。

如果将库发布到Pub站点,则需要的其他文件(如README和CHANGELOG)在发布包中进行了描述。 有关如何组织包目录的更多信息,请参见pub包布局约定

为一个库写文档

你可以使用dartdoc工具为你的库生成API文档。 Dartdoc解析源以查找使用///语法的文档注释

/// 负责处理在 ui 中更新 badge 的事件
void updateBadge() {
  ...
}

有关生成的文档的示例,请参阅shelf文档

注意:要在生成的文档中包括任何库级别的文档,必须指定指令。 请参阅问题1082

分发开源库

如果你的库是开源的,我们建议在Pub网站上共享它。 要发布或更新库,请使用pub publish,它会上传你的软件包并创建或更新其页面。 例如,请参阅shelf包页面。 有关如何准备要发布包的详细信息,请参见发布包。

发布网站不仅托管你的软件包,而且还生成并托管你的软件包的API参考文档。 软件包的About框中提供了最新生成的文档的链接; 例如,请参阅书架包装的API文档。 程序包页面的Versions标签中的指向先前版本文档的链接。

为确保你的软件包的API文档在发布网站上看起来不错,请按照以下步骤操作:

  • 在发布包之前,请运行dartdoc工具,以确保你的文档生成成功并且外观符合预期。
  • 发布包后,请检查Versions选项卡,以确保文档已成功生成。
  • 如果文档根本没有生成,请在Versions标签中单击failed以查看dartdoc输出。

资源

使用以下资源来了解有关库包的更多信息: