Flutter入门——使用库

Posted by lingjye on July 15, 2019

库和可见性

使用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;

懒加载一个库

延迟加载(懒加载)允许应用程序在需要库时按需加载库。使用懒加载的场景:

  1. 减少应用程序初始启动时间。
  2. 例如执行A/B测试-尝试(testing—trying)算法的替代实现。
  3. 加载很少使用的功能,例如可选的屏幕和对话框。
  • 只有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指令。

下面显示了一个基本库的布局:

package

一个库必须有:

  1. pubspec 文件

pubspec file是必须的,该pubspec.yaml文件和应用程序包中的文件相同,没有特殊的名来指示包是库。

  1. lib 目录

库代码位于lib目录下,并且对其他包是公开的。可以根据需要在lib下创建任何层次结构。按照惯例,实现代码放在lib/src下。lib/src下的代码被认为是私有的; 其他包不需要导入src/…下的文件。要公开lib/src下的API,可以将lib/src下的文件导出到lib下的一个文件中。

如果library未指定该指令,则会根据每个库的路径和文件名生成唯一标记。因此,除非要生成库级文档,否则我们建议您省略代码中的library指令

组织库源代码

大多数情况下,每个类都应该在自己的微型库中。使用part指令可以将库拆分为多个Dart文件。但是并不推荐使用part。

直接在库根目录下创建一个主库文件,lib/.dart,然后将所有的公开API导入。这样就可以只导入这一个文件来使用该库的所有功能。

lib目录还可能包含其他非src(non-src)下的库,比如该主库依赖了其他独立的库。下面的架包提供了一种简单的方法来使用Dart创建Web服务器:

dart-webserver

主库文件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:

import-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输出。