flutter 文件與庫(kù)的引用導(dǎo)出(import媒怯、import as订讼、import show、part扇苞、part of欺殿、library)

前言

dart語(yǔ)言的庫(kù)及其相關(guān)語(yǔ)法是了解dart應(yīng)用代碼組織的基礎(chǔ)寄纵。網(wǎng)上查找的相關(guān)資料往往只是涉及某幾個(gè)點(diǎn),很難有系統(tǒng)性的認(rèn)識(shí)脖苏,這里筆者將結(jié)合一些文檔和個(gè)人實(shí)踐經(jīng)驗(yàn)來(lái)對(duì)dart的庫(kù)及其相關(guān)語(yǔ)法進(jìn)行一個(gè)梳理程拭。

庫(kù)的引入

dart中,任意一個(gè)文件都會(huì)被認(rèn)為是一個(gè)庫(kù)棍潘,盡管其中可能并沒(méi)有library標(biāo)簽恃鞋,dart庫(kù)目前的引入方式大致有三種:

  • 引入dart語(yǔ)言的內(nèi)置庫(kù):
import 'dart:math';

引入內(nèi)置庫(kù)時(shí),在使用的uri中以dart:開頭

  • 引入pub包管理器提供庫(kù):
import 'package:flutter/material.dart';

在引用包管理器提供的庫(kù)時(shí)亦歉,uri中以package開頭

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

引用本地文件時(shí)恤浪,uri字符串中直接填寫文件的相對(duì)路徑。

指定庫(kù)的別名

兩個(gè)庫(kù)中如果存在相同的標(biāo)識(shí)符肴楷,在使用時(shí)很有可能會(huì)產(chǎn)生沖突资锰;或者在引入一個(gè)庫(kù)的內(nèi)容的時(shí)候,由于當(dāng)前文件引入的庫(kù)比較多阶祭,導(dǎo)致使用IDE工具提供的標(biāo)識(shí)符名稱聯(lián)想時(shí)绷杜,很有可能出現(xiàn)一些本不是我們想要選取,但是首字母相近的內(nèi)容濒募,影響編碼效率鞭盟,為此我們可以使用給庫(kù)指定別名的方法,來(lái)規(guī)避以上問(wèn)題瑰剃。

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

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

只引入庫(kù)的部分內(nèi)容

如果只想引入庫(kù)的部分內(nèi)容齿诉,可以使用如下語(yǔ)法:

// Import only foo.
import 'package:lib1/lib1.dart' show foo;

如果想屏蔽庫(kù)中的某些內(nèi)容,不引入這部分:

// Import all names EXCEPT foo.
import 'package:lib2/lib2.dart' hide foo;

關(guān)于part晌姚、library和part of

在具體業(yè)務(wù)中有以下痛點(diǎn):我們?cè)趹?yīng)用中定義了多個(gè)類或者其他方法粤剧,在引用時(shí)我們想只import一個(gè)文件就將相關(guān)內(nèi)容全部導(dǎo)出,如果將所有的類或者方法都放在一個(gè)文件中挥唠,會(huì)導(dǎo)致這個(gè)文件十分龐雜抵恋,不利于后續(xù)維護(hù)。為了解決這個(gè)問(wèn)題宝磨,我們可以使用part弧关、librarypart of來(lái)組織我們的代碼。
假設(shè)我們的存放公共類和方法的文件為為global.dart,其內(nèi)容可按如下方法組織:

//  定義庫(kù)的名字
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;

//  組成這個(gè)庫(kù)的其他文件
part './model/User.dart';
part './model/FriendInfo.dart';
part './model/Message.dart';

//  ...其他業(yè)務(wù)代碼

在文件的開頭使用library標(biāo)識(shí)符定義庫(kù)的名字唤锉,這也是其他子文件與其耦合起來(lái)的關(guān)鍵世囊,part標(biāo)識(shí)符指明組成這個(gè)庫(kù)的其他文件。需要注意的是窿祥,part部分一定要在import部分的后面株憾。
子文件的組織方式如下,以./model/FriendInfo.dart為例:

//  指明與其關(guān)聯(lián)的父庫(kù)
part of global;

//  定義其他內(nèi)容
class FriendInfo {
    ...
}

在子文件的開頭晒衩,使用part of標(biāo)識(shí)符嗤瞎,后跟父庫(kù)的名字墙歪,來(lái)指明從屬關(guān)系,注意子文件中不需要引入父庫(kù)中已經(jīng)引入的依賴猫胁。
在寫其他業(yè)務(wù)邏輯代碼的時(shí)候只需要直接引入global.dart文件即可:

import './global.dart';

延遲加載或者異步加載

延遲加載一個(gè)庫(kù)時(shí)箱亿,要使用deferred as來(lái)進(jìn)行導(dǎo)入:

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

在使用時(shí)跛锌,需要通用調(diào)用loadLibrary()來(lái)加載對(duì)應(yīng)的內(nèi)容

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

盡管你可能在項(xiàng)目中多次調(diào)用loadLibrary()來(lái)加載一個(gè)庫(kù)弃秆,但是這個(gè)庫(kù)也只會(huì)被加載一次。

編寫一個(gè)庫(kù)

庫(kù)是代碼復(fù)用和邏輯模塊化的絕佳手段髓帽。庫(kù)是以包的形式被創(chuàng)造和分發(fā)的菠赚。dart語(yǔ)言有兩種類型的包:包含本地庫(kù)的應(yīng)用包(application packages)和庫(kù)包(library packages).

  • 應(yīng)用包通常會(huì)依賴其他的包,但是絕不會(huì)有自引用郑藏,應(yīng)用包的反面就是庫(kù)包
  • 庫(kù)包是其他包的依賴對(duì)象衡查,他們自己也會(huì)依賴其他包,亦有可能會(huì)自引用必盖,它們中往往含有會(huì)直接運(yùn)行的腳本拌牲,庫(kù)包的反面就是應(yīng)用包

編寫一個(gè)庫(kù)包

下圖展示了一個(gè)最簡(jiǎn)單的庫(kù)包組成結(jié)構(gòu):

image.png

一個(gè)庫(kù)所需的最簡(jiǎn)內(nèi)容包括:

  1. pubspec 文件
    pubspec.yaml文件在庫(kù)包和應(yīng)用包中是類似的,二者并沒(méi)有區(qū)別歌粥。
  2. lib 目錄
    正如你直覺感覺的那樣塌忽,庫(kù)的代碼都在lib目錄下,這部分內(nèi)容對(duì)其他包也是可見的失驶。如果需要的話土居,你可以在lib文件夾下創(chuàng)造其他層級(jí)的文件,按照慣例嬉探,邏輯實(shí)現(xiàn)的代碼通常放在lib/src目錄下擦耀。在該目錄下的文件通常被認(rèn)為是私有的。其他的包不應(yīng)引入src目錄下的內(nèi)容從而暴露lib/scr中的API,正確的使用方法是從lib目錄下的其他文件中引出內(nèi)容涩堤。

組織一個(gè)庫(kù)包

當(dāng)你創(chuàng)建稱為迷你庫(kù)的小型獨(dú)立庫(kù)時(shí)眷蜓,庫(kù)包最容易維護(hù)、擴(kuò)展和測(cè)試胎围。在絕大多數(shù)情況下账磺,每一個(gè)類應(yīng)該都以一個(gè)迷你庫(kù)的形式存在,除非兩個(gè)類之間深度耦合痊远。
為了引出一個(gè)庫(kù)中的公共api,建議在lib目錄下創(chuàng)建一個(gè)'main'文件垮抗,方便使用者僅僅通過(guò)應(yīng)用單文件來(lái)獲取庫(kù)中的所有功能。lib目錄下也有可能包含其他可引入的庫(kù)碧聪。例如冒版,如果你的庫(kù)可以跨平臺(tái)工作,但是你創(chuàng)建了兩個(gè)不同的子文件分別依賴dart:io和datr:html逞姿。部分包引用了不同的庫(kù)辞嗡,在引用這部分內(nèi)容時(shí)需要給他們添加前綴捆等。 接下來(lái)我們觀察一個(gè)真實(shí)的庫(kù)包:shelf,這個(gè)包提供了使用Dart語(yǔ)法創(chuàng)建庫(kù)的服務(wù)器的方法,下圖是其的結(jié)構(gòu):

image.png

在lib目錄下的主文件shelf.dart暴露了lib/src下的其他文件中的內(nèi)容給使用者:

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è)迷你庫(kù)续室,shelf_io,他對(duì)dart:io中的http請(qǐng)求體進(jìn)行了簡(jiǎn)單的封裝栋烤。

引入庫(kù)文件

當(dāng)你引用一個(gè)庫(kù)文件的時(shí)候,你可以使用package:指令來(lái)指定該文件的URI挺狰。

import 'package:utilities/utilities.dart';

對(duì)于引用的文件和被引明郭,文件當(dāng)兩個(gè)文件都在lib內(nèi)部時(shí),或者當(dāng)兩個(gè)文件都在lib外部時(shí)丰泊,可以使用相對(duì)路徑導(dǎo)入庫(kù)薯定。當(dāng)其中一個(gè)文件在lib目錄內(nèi)或者外部時(shí),你必須使用package:瞳购。當(dāng)你舉棋不定的時(shí)候话侄,可以直接會(huì)用package:,這種語(yǔ)法在兩種情況下都可用。 下面的圖展示了如何分別從lib目錄和網(wǎng)絡(luò)引入lib/foo/a.dart

image.png

提供其他文件(測(cè)試代碼学赛、命令行工具)

一個(gè)設(shè)計(jì)良好的庫(kù)要便于測(cè)試年堆。我們推薦你使用test包來(lái)編寫測(cè)試用例,你可以把測(cè)試代碼放在包的頂級(jí)目錄中的test文件夾下盏浇。
如果你給用戶創(chuàng)建了命令行工具变丧,請(qǐng)將它們放在bin文件夾下,以便用戶可以直接通過(guò)pub global activate命令來(lái)使用命令行工具缠捌。將命令行工具寫在executables section以便用戶可以直接調(diào)用命令行代碼而無(wú)需調(diào)用pub global run方法.
任何庫(kù)自己私有的工具函數(shù)或代碼(你不想暴露給使用者),你可以將它們放在tool文件夾下锄贷。 關(guān)于其他你想要的推送到Pub站點(diǎn)的文件,例如README和CHANGELOG等等曼月,你可以在Publishing a Pageage中查閱具體內(nèi)容谊却。

給庫(kù)編寫注釋

你可以使用dartdoc工具來(lái)給你的庫(kù)添加API注釋。Dartdoc將會(huì)解析你的源碼哑芹,找到其中通過(guò)注釋語(yǔ)法標(biāo)記的內(nèi)容炎辨,標(biāo)記示例如下:

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

開源一個(gè)庫(kù)

如果你想要開源一個(gè)庫(kù),建議你將其分享在Pub site.可以使用pub publish命令來(lái)上傳或者更新一個(gè)庫(kù)聪姿。pub site不僅僅存儲(chǔ)你的庫(kù)碴萧,它同時(shí)也會(huì)自動(dòng)生成并且保存的你庫(kù)的api引用文檔。
為了確保你的包的API文檔生成正確末购,你可以遵循以下步驟:

  • 在你推送你的包之前破喻,運(yùn)行dartdoc工具確保你的文檔生成正確并且展示符合預(yù)期
  • 在你推送你的包之后,檢查Vesion tab去報(bào)你的文檔生成正確
  • 如果文檔生成失敗盟榴,檢查dartdoc的輸出

總結(jié)

  • import 'dart:xxx'; 引入Dart標(biāo)準(zhǔn)庫(kù)
  • import 'xxx/xxx.dart';引入絕對(duì)路徑的Dart文件
  • import 'package:xxx/xxx.dart'; 引入Pub倉(cāng)庫(kù)pub.dev(或者pub.flutter-io.cn)中的第三方庫(kù)
  • import 'package:project/xxx/xxx.dart';引入自定義的dart文件
  • import 'xxx' show compute1曹质,compute2 只導(dǎo)入compute1,compute2
  • import 'xxx' hide compute3 除了compute都引入
  • import 'xxx' as compute4 將庫(kù)重命名,當(dāng)有名字沖突時(shí)
  • library compute5; 定義庫(kù)名稱
  • part of compute6; 表示文件屬于某個(gè)庫(kù)

文件導(dǎo)入順序(從上到下依次)

dart sdk 內(nèi)的庫(kù)
flutter內(nèi)的庫(kù)
第三方庫(kù)
自己的庫(kù)(文件)
相對(duì)路徑引用
e.g.
import 'dart:io';
import 'package:material/material.dart';
import 'package:dio/dio.dart';
import 'package:project/common/uitls.dart';
import 'xxx/xxx/xxx/xxx.dart';

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末羽德,一起剝皮案震驚了整個(gè)濱河市几莽,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌宅静,老刑警劉巖章蚣,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異姨夹,居然都是意外死亡纤垂,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門匀伏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)洒忧,“玉大人蝴韭,你說(shuō)我怎么就攤上這事够颠。” “怎么了榄鉴?”我有些...
    開封第一講書人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵履磨,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我庆尘,道長(zhǎng)剃诅,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任驶忌,我火速辦了婚禮矛辕,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘付魔。我一直安慰自己聊品,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開白布几苍。 她就那樣靜靜地躺著翻屈,像睡著了一般。 火紅的嫁衣襯著肌膚如雪妻坝。 梳的紋絲不亂的頭發(fā)上伸眶,一...
    開封第一講書人閱讀 51,301評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音刽宪,去河邊找鬼厘贼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛圣拄,可吹牛的內(nèi)容都是我干的嘴秸。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼赁遗!你這毒婦竟也來(lái)了署辉?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤岩四,失蹤者是張志新(化名)和其女友劉穎哭尝,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體剖煌,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡材鹦,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了耕姊。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片桶唐。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖茉兰,靈堂內(nèi)的尸體忽然破棺而出尤泽,到底是詐尸還是另有隱情,我是刑警寧澤规脸,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布坯约,位于F島的核電站,受9級(jí)特大地震影響莫鸭,放射性物質(zhì)發(fā)生泄漏闹丐。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一被因、第九天 我趴在偏房一處隱蔽的房頂上張望卿拴。 院中可真熱鬧,春花似錦梨与、人聲如沸堕花。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)航徙。三九已至,卻和暖如春陷虎,著一層夾襖步出監(jiān)牢的瞬間到踏,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工尚猿, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留窝稿,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓凿掂,卻偏偏與公主長(zhǎng)得像伴榔,于是被迫代替她去往敵國(guó)和親纹蝴。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容