dart flutter 文件與庫的引用導出

前言

  dart語言的庫及其相關語法是瞭解dart應用代碼組織的基礎。網上查找的相關資料每每只是涉及某幾個點,很難有系統性的認識,這裏筆者將結合一些文檔和我的實踐經驗來對dart的庫及其相關語法進行一個梳理。html

庫的引入

  dart中,任意一個文件都會被認爲是一個庫,儘管其中可能並無library標籤,dart庫目前的引入方式大體有三種:git

  • 引入dart語言的內置庫:
import 'dart:math';
複製代碼

引入內置庫時,在使用的uri中以dart:開頭github

  • 引入pub包管理器提供庫:
import 'package:flutter/material.dart';
複製代碼

在引用包管理器提供的庫時,uri中以package開頭c#

  • 引入本地文件:
import './tools/network.dart';
複製代碼

引用本地文件時,uri字符串中直接填寫文件的相對路徑。api

指定庫的別名

兩個庫中若是存在相同的標識符,在使用時頗有可能會產生衝突;或者在引入一個庫的內容的時候,因爲當前文件引入的庫比較多,致使使用IDE工具提供的標識符名稱聯想時,頗有可能出現一些本不是咱們想要選取,可是首字母相近的內容,影響編碼效率,爲此咱們可使用給庫指定別名的方法,來規避以上問題。bash

import 'package:socket_io_client/socket_io_client.dart' as IO;

class MySocketIO {
  IO.Socket mySocket;
  MySocketIO(this.mySocket);
}

複製代碼

只引入庫的部份內容

若是隻想引入庫的部份內容,可使用以下語法:服務器

// Import only foo.
import 'package:lib1/lib1.dart' show foo;
複製代碼

若是想屏蔽庫中的某些內容,不引入這部分:網絡

// Import all names EXCEPT foo.
import 'package:lib2/lib2.dart' hide foo;
複製代碼

關於part、library和part of

在具體業務中有如下痛點:咱們在應用中定義了多個類或者其餘方法,在引用時咱們想只import一個文件就將相關內容所有導出,若是將全部的類或者方法都放在一個文件中,會致使這個文件十分龐雜,不利於後續維護。爲了解決這個問題,咱們可使用partlibrarypart of來組織咱們的代碼。
假設咱們的存放公共類和方法的文件爲爲global.dart,其內容可按以下方法組織:app

//  定義庫的名字
library global;

//  文件中引用的公共包
import 'dart:convert';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:i_chat/tools/utils.dart';
import 'package:shared_preferences/shared_preferences.dart';
import './tools/network.dart';
import 'package:dio/dio.dart';
import 'dart:math';
import 'package:provider/provider.dart';
import 'package:socket_io_client/socket_io_client.dart' as IO;

//  組成這個庫的其餘文件
part './model/User.dart';
part './model/FriendInfo.dart';
part './model/Message.dart';

//  ...其餘業務代碼
複製代碼

在文件的開頭使用library標識符定義庫的名字,這也是其餘子文件與其耦合起來的關鍵,part標識符指明組成這個庫的其餘文件。須要注意的是,part部分必定要在import部分的後面。
子文件的組織方式以下,以./model/FriendInfo.dart爲例:異步

//  指明與其關聯的父庫
part of global;

//  定義其餘內容
class FriendInfo {
    ...
}
複製代碼

在子文件的開頭,使用part of標識符,後跟父庫的名字,來指明從屬關係,注意子文件中不須要引入父庫中已經引入的依賴。
在寫其餘業務邏輯代碼的時候只須要直接引入global.dart文件便可:

import './global.dart';
複製代碼

延遲加載或者異步加載

延遲加載一個庫時,要使用deferred as來進行導入:

import 'package:greetings/hello.dart' deferred as hello;
複製代碼

在使用時,須要通用調用loadLibrary()來加載對應的內容

Future greet() async {
  await hello.loadLibrary();
  hello.printGreeting();
}
複製代碼

儘管你可能在項目中屢次調用loadLibrary()來加載一個庫,可是這個庫也只會被加載一次。

編寫一個庫

庫是代碼複用和邏輯模塊化的絕佳手段。庫是以包的形式被創造和分發的。dart語言有兩種類型的包:包含本地庫的應用包(application packages)和庫包(library packages).

  • 應用包一般會依賴其餘的包,可是毫不會有自引用,應用包的反面就是庫包
  • 庫包是其餘包的依賴對象,他們本身也會依賴其餘包,亦有可能會自引用,它們中每每含有會直接運行的腳本,庫包的反面就是應用包

編寫一個庫包

下圖展現了一個最簡單的庫包組成結構:

極簡庫包結構圖

一個庫所需的最簡內容包括:

  1. pubspec 文件
    pubspec.yaml文件在庫包和應用包中是相似的,兩者並無區別。
  2. lib 目錄
    正如你直覺感受的那樣,庫的代碼都在lib目錄下,這部份內容對其餘包也是可見的。若是須要的話,你能夠在lib文件夾下創造其餘層級的文件,按照慣例,邏輯實現的代碼一般放在lib/src目錄下。在該目錄下的文件一般被認爲是私有的。其餘的包不該引入src目錄下的內容從而暴露lib/scr中的API,正確的使用方法是從lib目錄下的其餘文件中引出內容。

組織一個庫包

當你建立稱爲迷你庫的小型獨立庫時,庫包最容易維護、擴展和測試。在絕大多數狀況下,每個類應該都以一個迷你庫的形式存在,除非兩個類之間深度耦合。
爲了引出一個庫中的公共api,建議在lib目錄下建立一個'main'文件,方便使用者僅僅經過應用單文件來獲取庫中的全部功能。lib目錄下也有可能包含其餘可引入的庫。例如,若是你的庫能夠跨平臺工做,可是你建立了兩個不一樣的子文件分別依賴dart:io和datr:html。部分包引用了不一樣的庫,在引用這部份內容時須要給他們添加前綴。 接下來咱們觀察一個真實的庫包:shelf,這個包提供了使用Dart語法建立庫的服務器的方法,下圖是其的結構:

shelf庫結構圖

在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包還包括一個迷你庫,shelf_io,他對dart:io中的http請求體進行了簡單的封裝。

引入庫文件

當你引用一個庫文件的時候,你可使用package:指令來指定該文件的URI。

import 'package:utilities/utilities.dart';
複製代碼

對於引用的文件和被引,文件當兩個文件都在lib內部時,或者當兩個文件都在lib外部時,可使用相對路徑導入庫。當其中一個文件在lib目錄內或者外部時,你必須使用package:。當你猶豫不定的時候,能夠直接會用package:,這種語法在兩種狀況下均可用。 下面的圖展現瞭如何分別從lib目錄和網絡引入lib/foo/a.dart

文件引入示意圖

提供其餘文件(測試代碼、命令行工具)

一個設計良好的庫要便於測試。咱們推薦你使用test包來編寫測試用例,你能夠把測試代碼放在包的頂級目錄中的test文件夾下。
若是你給用戶建立了命令行工具,請將它們放在bin文件夾下,以便用戶能夠直接經過pub global activate命令來使用命令行工具。將命令行工具寫在executables section以便用戶能夠直接調用命令行代碼而無需調用pub global run方法.
任何庫本身私有的工具函數或代碼(你不想暴露給使用者),你能夠將它們放在tool文件夾下。 關於其餘你想要的推送到Pub站點的文件,例如README和CHANGELOG等等,你能夠在Publishing a Pageage中查閱具體內容。

給庫編寫註釋

你可使用dartdoc工具來給你的庫添加API註釋。Dartdoc將會解析你的源碼,找到其中經過註釋語法標記的內容,標記示例以下:

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

開源一個庫

若是你想要開源一個庫,建議你將其分享在Pub site.可使用pub publish命令來上傳或者更新一個庫。pub site不只僅存儲你的庫,它同時也會自動生成而且保存的你庫的api引用文檔。
爲了確保你的包的API文檔生成正確,你能夠遵循如下步驟:

  • 在你推送你的包以前,運行dartdoc工具確保你的文檔生成正確而且展現符合預期
  • 在你推送你的包以後,檢查Vesion tab去報你的文檔生成正確
  • 若是文檔生成失敗,檢查dartdoc的輸出

參考文獻

相關文章
相關標籤/搜索