(九)Dart Libraries(庫)、package(包)

庫可以使用 Dart package 工具部署。參考 Pub Package 和 Asset Manager 來獲取關(guān)于 pub(Dart 的包管理工具) 的更多信息。

使用 importlibrary 指令可以幫助你創(chuàng)建 模塊化的可分享的代碼。庫不僅僅提供 API, 還是一個(gè)私有單元:以下劃線 (_) 開頭的標(biāo)識符只有在庫 內(nèi)部可見。每個(gè) Dart app 都是一個(gè)庫, 即使沒有使用 library 命令也是一個(gè)庫。

一、Using libraries(使用庫)

使用 import 來指定一個(gè)庫如何使用另外 一個(gè)庫。

例如, Dart web 應(yīng)用通常使用 dart:html 庫,然后可以這樣導(dǎo)入庫:

import 'dart:html';

import 必須參數(shù)為庫 的 URI。 對于內(nèi)置的庫,URI 使用特殊的 dart: scheme。 對于其他的庫,你可以使用文件系統(tǒng)路徑或者 package:scheme。package: scheme 指定的庫通過包管理器來提供, 例如 pub 工具。

import 'dart:io';
import 'package:mylib/mylib.dart';
import 'package:utils/utils.dart';

注意: URI 代表 uniform resource identifier。 URLs (uniform resource locators) 是一種常見的 URI。

二、Specifying a library prefix(指定庫前綴)

如果你導(dǎo)入的兩個(gè)庫具有沖突的標(biāo)識符, 則你可以使用庫的前綴來區(qū)分。 例如,如果 library1 和 library2 都有一個(gè)名字為 Element 的類, 你可以這樣使用:

import 'package:lib1/lib1.dart';
import 'package:lib2/lib2.dart' as lib2;
// ...
Element element1 = new Element();           // 使用lib1的Element .
lib2.Element element2 = new lib2.Element(); // 使用lib2的Element.

三、Importing only part of a library(導(dǎo)入庫的一部分)

如果你只使用庫的一部分功能,則可以選擇需要導(dǎo)入的 內(nèi)容。例如:

// 僅導(dǎo)入 foo.
import 'package:lib1/lib1.dart' show foo;

// 除了 foo,其他都導(dǎo)入.
import 'package:lib2/lib2.dart' hide foo;

四、Lazily loading a library(延遲載入庫)

Deferred loading (也稱之為 lazy loading) 可以讓應(yīng)用在需要的時(shí)候再 加載庫。 下面是一些使用延遲加載庫的場景:

  • 減少 APP 的啟動(dòng)時(shí)間。
  • 執(zhí)行 A/B 測試,例如 嘗試各種算法的 不同實(shí)現(xiàn)。
  • 加載很少使用的功能,例如可選的屏幕和對話框。

要延遲加載一個(gè)庫,需要先使用 deferred as 來 導(dǎo)入:

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

當(dāng)需要使用的時(shí)候,使用庫標(biāo)識符調(diào)用 loadLibrary() 函數(shù)來加載庫:

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

在前面的代碼, 使用 await 關(guān)鍵字暫停代碼執(zhí)行一直到庫加載完成。 關(guān)于 asyncawait 的更多信息請參考第十章。

在一個(gè)庫上你可以多次調(diào)用 loadLibrary() 函數(shù)。 但是該庫只是載入一次。

使用延遲加載庫的時(shí)候,請注意一下問題:
1、延遲加載庫的常量在導(dǎo)入的時(shí)候是不可用的。 只有當(dāng)庫加載完畢的時(shí)候,庫中常量才可以使用。
2、在導(dǎo)入文件的時(shí)候無法使用延遲庫中的類型。 如果你需要使用類型,則考慮把接口類型移動(dòng)到另外一個(gè)庫中, 讓兩個(gè)庫都分別導(dǎo)入這個(gè)接口庫。
3、Dart 隱含的把 loadLibrary() 函數(shù)導(dǎo)入到使用 deferred as *的命名空間* 中。 loadLibrary() 方法返回一個(gè) Future(詳情見第十章)。

五、package(包)Implementing libraries(實(shí)現(xiàn)庫)

在 Dart 生態(tài)中, 庫通過包的方式來創(chuàng)建和分發(fā)。 Dart 有兩種類型的包: 應(yīng)用包 和 庫包

5.1.應(yīng)用包

5.2.庫包

5.2.1.What makes a library package(庫包做了啥)

下面顯示了最簡單的庫包的 目錄結(jié)構(gòu):

最簡單的庫包的 目錄結(jié)構(gòu)

對于一個(gè)最簡單的庫需要如下內(nèi)容:

  • pubspec file
    庫的pubspec.yaml 文件和應(yīng)用包的一樣 —并沒有特別的標(biāo)志表明包是 一個(gè)庫。

  • lib directory
    庫包的代碼位于 lib 目錄中, 在其他包中可以訪問這里面的代碼。 在 lib 目錄下可以創(chuàng)建任意的目錄結(jié)構(gòu)。 通常情況下都把實(shí)現(xiàn)代碼放到 lib/src 目錄中。 位于 lib/src 下面的代碼被認(rèn)為是私有的; 其他包不應(yīng)該直接導(dǎo)入 src/... 里面的代碼。 要分享 lib/src 下的 API,你可以在 lib 目錄下 創(chuàng)建一個(gè)文件,在這個(gè)文件中導(dǎo)入 lib/src 中的代碼。

注意: 當(dāng)沒有指定 library 指令的時(shí)候,根據(jù)每個(gè)庫 的路徑和文件名會為每個(gè)庫生成一個(gè)唯一的標(biāo)簽。 所以,我們 建議你不要在代碼中使用 library 指令, 除非你想 生成庫的 API 文檔(詳見本文下面的Documenting a library)

在 lib 目錄下創(chuàng)建一個(gè)主要的庫文件( lib/<package-name>.dart),并且在該文件中 導(dǎo)出所有公開的 API。 這樣使用你的庫的用戶就可以只導(dǎo)入一個(gè) 文件就可以使用所有的功能了。

lib 目錄還可以包含其他重要的非代碼文件。例如, 你的庫是跨平臺的,你創(chuàng)建 了不同平臺使用 dart:io 的庫。 有些包有幾個(gè)分開的庫需要分別導(dǎo)入, 每個(gè)庫都使用不同的前綴。

下面是 shelf 庫的目錄結(jié)構(gòu)。 shelf 庫提供了一種簡單的方式來創(chuàng)建 web 服務(wù)器, shelf 的目錄結(jié)構(gòu)是 Dart 庫包目錄結(jié)構(gòu) 的常見形式:

shelf 的目錄結(jié)構(gòu)

在 lib 目錄下有個(gè)主要的庫文件 shelf.dart,該文件導(dǎo)出了 lib/src 目錄下的幾個(gè)文件:

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 庫還包含了一個(gè)迷你庫: shelf_io。 這個(gè)適配器處理 dart:io 中的 HttpRequest 對象。

5.2.2.Organizing a library package

當(dāng)庫包非常小的時(shí)候,是非常容易維護(hù)、擴(kuò)展和測試的, 這樣的庫被稱之為 迷你庫。 在大部分情況下,每個(gè)類都應(yīng)該位于一個(gè)迷你庫中, 除非當(dāng)兩個(gè)類緊緊耦合在一起的時(shí)候需要放到同一個(gè)庫中。

注意: 你可能已經(jīng)知道 part 指令了,該指令 可以把一個(gè)庫分開到多個(gè) Dart 文件中。我們推薦你 使用迷你庫,而不要使用該指令。

5.2.3.Importing library files

可以使用 package: 指令并指定文件的 URI 來 導(dǎo)入庫文件。

import 'package:utilities/utilities.dart';

當(dāng)兩個(gè)文件都位于 lib 目錄中 或者目錄 lib 之外的時(shí)候, 可以使用相對路徑來導(dǎo)入庫文件。

然后,當(dāng)導(dǎo)入的文件和使用的文件不在 同一個(gè)庫的時(shí)候,需要使用 package: 指令。 當(dāng)你不知道如何選擇的時(shí)候,就使用 package: 指令。

下面顯示了在 lib 和 web 庫中如何導(dǎo)入 lib/src/foo/a.dart

5.2.4.Providing additional files

良好的庫應(yīng)該很容易測試。 我們推薦你使用 test 庫來編寫測試代碼, 把測試代碼放到 test 目錄 下。

如果你創(chuàng)建了一個(gè)可執(zhí)行的工具,則可以把 這些工具放到 bin 目錄,該目錄是公開可訪問的。 使用 pub global activate 來啟用命令行運(yùn)行工具的功能。 在 executables 部分 列出所有可執(zhí)行文件, 可以讓用戶直接運(yùn)行該命令,而不用通過 pub global run 來執(zhí)行。

在庫中包含使用你的庫的示例代碼也是非常有用的,把這些代碼 放到 example 目錄下。

你在開發(fā)的時(shí)候創(chuàng)建的其他不應(yīng)該共享的工具則可以 放到 tool 目錄。

當(dāng)你把庫提交到 pub.dartlang.org 的時(shí)候,需要包含 README 、 CHANGELOG 等文件, 在 發(fā)布包 頁面對這些文件有介紹。 同時(shí)還請參考 Pub 包約定目錄結(jié)構(gòu) 來了解該如何布局包中的文件 目錄。

六、Documenting a library(生成庫的 API 文檔)

使用 dartdoc 工具可以 為庫生成 API 文檔。 Dartdoc 從代碼中解析 使用 /// 語法的 文檔注釋。

/// The event handler responsible for updating the badge in the UI.
void updateBadge() {
  ...
}

參考 shelf 文檔 來查看生成的 API 文檔格式。

注意: 要包含 庫的文檔需要使用 library 指令。 參考 issue 1082 了解詳情。

七、Distributing a library

當(dāng)把庫項(xiàng)目提交到版本庫中的時(shí)候,請注意有些 文件是不需要提交的。對于庫 不要提交 .packages、 pubspec.lock 文件, 也不要提交 packages 目錄。詳情請參考: 哪些文件不需要提交到版本庫。

使用 pub publish 工具可以在 pub.dartlang.org 上 分享你的庫。

發(fā)布一個(gè)庫 描述了一個(gè)庫需要包含哪些文件。

dartdocs.org 生成器 提供了一些好用的服務(wù)供發(fā)布到 pub.dartlang.org 的開發(fā)者使用。 這些服務(wù)追蹤庫的版本發(fā)布,當(dāng)有新版本發(fā)布的時(shí)候會自動(dòng) 生成新的 API 文檔,文檔在 dartdocs.org 可以查看。 在發(fā)布你的庫之前,請先運(yùn)行 dartdoc 看看生成 的文檔是否滿足你的要求。 如果你的庫的文檔在 dartdocs.org 中查找不到,請 查看 dartdocs.org/failed 來了解原因。

為了避免版本發(fā)布引起的問題, 當(dāng)引用 dartdocs.org 地址的時(shí)候, 可以指定 “l(fā)atest” 版本來替代具體的版本號。 例如: https://www.dartdocs.org/documentation/shelf/latest/.

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容