一家之言,勿噴偎窘。若有更好方案乌助,歡迎共享。
前言
關(guān)于 Flutter
的教程已經(jīng)有很多了陌知,也有很多優(yōu)秀的開(kāi)源項(xiàng)目他托,這在一定程度上也增加了社區(qū)的活躍度。同時(shí)也有很多商業(yè)項(xiàng)目在實(shí)踐仆葡,不過(guò)多數(shù)是將Flutter
工程作為一個(gè)module
來(lái)嵌入原生工程赏参。官方有對(duì)應(yīng)的教程來(lái)指導(dǎo)相關(guān)的工程化,網(wǎng)上的教程也很多。
但是一個(gè)純 Flutter
工程的分層架構(gòu)設(shè)計(jì)以及工程化的教程并不是很多把篓。恰巧最近有個(gè)項(xiàng)目需要基于 Flutter
工程來(lái)搭建纫溃,對(duì)分層設(shè)計(jì)以及相應(yīng)的工程化做了一些思考和調(diào)研,此倉(cāng)庫(kù)的目的即在于記錄方案韧掩,與大家分享皇耗。
分層設(shè)計(jì)
分層設(shè)計(jì)和目前成熟的移動(dòng)端的分層設(shè)計(jì)差不多,都是根據(jù)基礎(chǔ)能力和業(yè)務(wù)模塊對(duì) App
進(jìn)行分層以及組件劃分揍很,從而達(dá)到組件化的目的。
例如下圖是一個(gè)很常見(jiàn)的移動(dòng)端分層設(shè)計(jì)万伤。
將與業(yè)務(wù)無(wú)關(guān)的基礎(chǔ)能力剝離出來(lái)窒悔,沉淀到最底層,上層的業(yè)務(wù)都會(huì)基于這些能力去構(gòu)建敌买;中間劃出一個(gè)業(yè)務(wù)能力層简珠,多數(shù)是一些弱業(yè)務(wù)邏輯的模塊,像分享虹钮、支付這樣的能力聋庵;然后是業(yè)務(wù)模塊,這些基本上就是用戶(hù)可感知的界面以及業(yè)務(wù)邏輯了芙粱;最后是宿主App
祭玉。基于這樣的分層設(shè)計(jì)春畔,宿主App
一般都是個(gè)殼工程脱货。
針對(duì)這樣的設(shè)計(jì),相應(yīng)的組件間通信方案律姨、工程化方案都已經(jīng)很成熟振峻,而且可選方案也很多。這里不再贅述择份,感興趣的可以自行Google
扣孟。
所以我們的Flutter
應(yīng)該也是可以按照這樣的分層去設(shè)計(jì),但是由于Flutter
開(kāi)發(fā)中可能會(huì)遇到需要原生提供能力的場(chǎng)景荣赶,這樣就會(huì)有一部分能力是基于原生能力封裝的插件凤价,但總的分層設(shè)計(jì)還是類(lèi)似的。例如下圖的分層設(shè)計(jì):
工程化實(shí)踐
目前網(wǎng)絡(luò)上關(guān)于這一塊的討論比較少讯壶,如果你有看到相關(guān)的文章料仗,歡迎共享。鑒于組內(nèi)iOS
的小伙伴是使用VSCode
來(lái)開(kāi)發(fā)的伏蚊,所以工程化實(shí)踐也是基于VSCode
來(lái)操作的立轧,不過(guò)這個(gè)應(yīng)該影響不大。
模板工程介紹
我們先了解一下Flutter
為我們提供的4
中模板工程:App、Module氛改、Plugin帐萎、Package
。
App
我們一般都是創(chuàng)建一個(gè)App
工程胜卤,這個(gè)模板工程會(huì)有android
疆导、ios
目錄,對(duì)應(yīng)存放的是兩個(gè)平臺(tái)的工程葛躏。
Module
使用這個(gè)模板創(chuàng)建出來(lái)的工程澈段,會(huì)有.android
、.ios
目錄舰攒,從模板的名稱(chēng)可以猜到應(yīng)該是作為Module
來(lái)使用的败富,官方對(duì)于這個(gè)模板的應(yīng)用場(chǎng)景是將Flutter
作為原生的一個(gè)子Module
。這個(gè)模板創(chuàng)建的時(shí)候也會(huì)有main.dart
文件摩窃,可以單獨(dú)運(yùn)行在你的設(shè)備上兽叮。
Plugin
如果你需要封裝基于原生能力的插件,就需要用到這個(gè)模板猾愿。
Package
這是一個(gè)純Flutter
模塊鹦聪,沒(méi)有android
、ios
目錄蒂秘。
pubspec.yaml
配置介紹
看過(guò)Flutter
教程的應(yīng)該都了解泽本,如果我們需要引用一些第三方庫(kù),就可以在這里配置材彪,一般我們配置的都是發(fā)布在 pub.dev
上的開(kāi)源項(xiàng)目观挎。但其實(shí),除了可以直接依賴(lài)pub.dev
段化,他還支持本地依賴(lài)嘁捷,git
倉(cāng)庫(kù)依賴(lài)。你可以這樣操作:
dependencies:
plugin1:
git:
url: "git://github.com/flutter/plugin1.git"
fish_redux:
path: my_package/fish_redux-0.3.1
另外git
依賴(lài)還支持指定branch
显熏,指定子目錄等雄嚣。
好了,鋪墊了這么多喘蟆,是時(shí)候介紹我們的工程化方案了缓升。
具體方案
鑒于目前還處于初步實(shí)踐階段,所以并沒(méi)有將各個(gè)組件上傳到git
倉(cāng)庫(kù)蕴轨,而是采用基于本地依賴(lài)的方式港谊。因?yàn)楦鱾€(gè)組件可能會(huì)頻繁變動(dòng),就會(huì)不停的切換工程等橙弱。等后期穩(wěn)定后歧寺,可以采用git
依賴(lài)的方式燥狰,達(dá)到供多個(gè)App
使用的目的。
先來(lái)看一下整個(gè)工程的目錄結(jié)構(gòu)斜筐,如果你有一定的分層設(shè)計(jì)經(jīng)驗(yàn)龙致,應(yīng)該很容易理解這個(gè)目錄結(jié)構(gòu)的設(shè)計(jì)。
HostApp
:殼工程目錄
BusinessModule
:業(yè)務(wù)模塊目錄
BusinessLib
:業(yè)務(wù)能力目錄顷链,里面還有個(gè)二級(jí)的UI
目錄目代,存放一些和業(yè)務(wù)相關(guān)的公共UI
組件
CommonLib
:基礎(chǔ)能力目錄
按照上面的思路,我們首先需要一個(gè)殼工程嗤练,我們使用VSCode
新建一個(gè)App
工程榛了,這里放在HostApp
目錄下。
接著我們?cè)?code>BusinessModule中新建四個(gè)業(yè)務(wù)模塊工程煞抬,這次我們不再新建App
工程忽冻,而是新建Module
工程。我這邊新建了module_home
此疹、module_user
、module_task
遮婶、module_setting
四個(gè)工程蝗碎。
同樣,我們?cè)?code>BusinessLib中也新建幾個(gè)工程旗扑,供測(cè)試使用蹦骑,這里新建了lib_account
、lib_push
臀防、lib_share
眠菇,然后在UI
目錄中新建了lib_alert
、lib_banner
袱衷、lib_loading
捎废。在CommonLib
新建lib_database
、lib_log
致燥、lib_network
登疗。其中lib_account
、lib_database
嫌蚤、lib_network
是Package
工程辐益,lib_push
、lib_share
脱吱、lib_alert
智政、lib_banner
、lib_loading
是Module
工程箱蝠,lib_log
是Plugin
工程续捂。大家根據(jù)自己的實(shí)際場(chǎng)景去新建對(duì)應(yīng)的模板工程垦垂。
這樣所有的工程都放在對(duì)應(yīng)的目錄,為了方便管理疾忍,我們新建一個(gè)workspace
來(lái)管理所有的工程乔外。具體可以這樣操作:
- 在
VSCode
中New Window
-
Add Folder to Workspace...
,選擇我們的根目錄 -
Save Workspace As...
一罩,保存到我們的根目錄
下次可以直接打開(kāi)我們的workspace
文件杨幼。
現(xiàn)在打開(kāi)host_app
工程的pubspec.yaml
做如下配置掀亩,將BusinessModule
中的組件引入進(jìn)來(lái)阁苞。
dependencies:
module_home:
path: ../../BusinessModule/module_home
module_user:
path: ../../BusinessModule/module_user
module_setting:
path: ../../BusinessModule/module_setting
module_task:
path: ../../BusinessModule/module_task
保存后運(yùn)行flutter pub get
。
這里有個(gè)小問(wèn)題耕肩,就是使用
workspace
后汉嗽,在host_app
里面去引用module_home
內(nèi)定義的頁(yè)面欲逃,沒(méi)有代碼提示,但是手動(dòng)import
后饼暑,編譯都正常稳析。不知道是Bug
還是我使用的有問(wèn)題。
我們?cè)?code>module_home弓叛、module_user
彰居、module_setting
、module_task
中各新建一個(gè)頁(yè)面撰筷,HomePage
陈惰、UserPage
、SettingPage
毕籽、TaskPage
抬闯。
我們?cè)?code>host_app的入口構(gòu)建一個(gè)Tab
頁(yè)面,將我們的HomePage
关筒、UserPage
作為兩個(gè)Tab
加載進(jìn)來(lái)溶握。試著運(yùn)行一下,感覺(jué)良好蒸播。
哇哦奈虾,基本的框架已經(jīng)搭建出來(lái)了,雖然后續(xù)需要處理的事情還有很多廉赔,例如組件間的頁(yè)面如何跳轉(zhuǎn)肉微、組件間如何通信,都需要有對(duì)應(yīng)的方案實(shí)現(xiàn)蜡塌。
且等我繼續(xù)調(diào)研實(shí)踐碉纳。