作者:騰訊 - 小德(koudleren 任曉帥)
前言
前面講了Flutter和Native的混合開發模式,Flutter作為Native工程的一個Module存在,這樣可以有效的將Flutter和Native進行物理隔離,但隨著Flutter承載的業務越來越多,與Native互動的介面變的越來越多,帶來了很多管理問題,因此我們迫切需要採用新的開發模式,本文將介紹Flutter的元件化開發方案。
1.存在的問題
- 因為互動介面涉及Flutter、Android、iOS多端,隨著介面變的越來越多,使得工程越來越複雜,程式碼也越來越多,導致維護成本變高,不好管理。
- 眾多的介面寫在一起,邏輯耦合,修改一處可能會影響其他的邏輯,也不好複用。
- 不方便單元測試
2.改進點
採用元件化開發Flutter,將會有如下的優勢:
- 將功能模組化,相互獨立,方便管理
- 模組之間互不影響,耦合低,一些與業務無關的模組可以開源出來,供其他APP使用,提供程式碼的複用。
- 採用元件化開發,開發時互不影響,可以提高開發效率。
- 方便單元測試
下面介紹Flutter元件化開發的具體內容。
3.從Platform Channel說起
- 定義
Platform Channel為Dart和平臺之間提供了相互通訊的機制,將Flutter、Android、iOS連線起來。
複製程式碼
在移動H5開發中,webview自身提供的功能往往不夠用,為了解決這個問題,引入了jsbridge,即web與native之間進行資料互動的一種方法,可以方便的將native的功能擴充套件給webview使用,從而可以快速開發。在Flutter中,也存在和jsbridge一樣的用法,那就是Platform Channel,我們可以通過Platform Channel,將Flutter和Native方便的連線在一起,架構圖如下:
在Channel中
- client傳送資訊
- host接受資訊並返回結果
- 而且訊息和響應是以非同步方式傳遞的
- Flutter和Natvie可以互為client和host,資訊傳遞是雙向的
而且在Flutter中實現一個Channel也非常簡單,假如Flutter作為client,Native作為Host,只需要:
- 在Flutter層宣告一個Channel,傳送訊息到Native,等待Native結果返回
static const platform = const MethodChannel(‘samples.flutter.io/battery');
int result = await platform.invokeMethod('getBatteryLevel');
複製程式碼
- 在Native層註冊Channel的監聽,當收到從Flutter層傳送過來的訊息時,將結果返回給Flutter
new MethodChannel(getFlutterView(),"samples.flutter.io/battery").setMethodCallHandler(
new MethodCallHandler() {
@Override
public void onMethodCall(MethodCall call, Result result) {
if (call.method.equals("getBatteryLevel")) {
return batteryLevel;
}
}}
);
複製程式碼
從中我們可以發現,寫一個Flutter的Platform Channel非常簡潔而且輕量。而且相較於H5的jsbridge,Platform Channel也具有如下的幾個優勢:
- Platform Channel是Flutter自帶的功能,不需要額外的開發,介面簡潔,呼叫方便。
- Platform Channel比jsbridge有更好的效能表現
- 更重要的是Platform Channel底層實現統一,更聚焦於資料之間的傳遞,不像jsbridge,如果使採用不同方法實現的jsbridge,程式碼是無法通用的,而Platform Channel卻可以做到更通用,
Platform Channel作為連線Flutter和Native的部分,在混合開發模式中非常重要,是作為底層重要架構的存在,因此可以將Platform Channel單獨作為一個模組,將Flutter工程中的Plaform Channel和UI程式碼分開,那麼如何將Platform Channel模組化呢?這裡就要講到一個新的概念:Flutter plugin.
4.Flutter Plugin
- 定義
一個在Android、iOS、Dart上實現Platform Channel程式碼的軟體包
複製程式碼
因此一個完整的Flutter Plugin 包含三種平臺的程式碼:
- Android平臺的Java或Kotlin
- iOS平臺的ObjC或者Swift
- Flutter平臺的Dart
所以Platform Channel可以使用Flutter plugin來實現模組化,這意味著可以將一些通用的功能在不同的APP上使用,例如:登入模組、圖片庫模組、網路庫模組、資料庫模組等。
建立Flutter Plugin的方法也很簡單:
- Android Studio
在Android Studio上安裝Flutter的外掛後,可以通過:
File
-> New
-> New Flutter Project...
-> Flutter Pulgin
- 命令列
$ flutter create --org com.example --template=plugin hello
複製程式碼
在建立完工程後,我們就可以實現我們想要的Platform Channel功能。那我們又如何共享我們的Flutter Plugin呢?熟悉Android開發的同學,都知道Maven倉庫,Flutter也有類似的軟體包倉庫,就是Pub.
5.Pub
- 定義
Pub是Dart語言的包管理器,包含Flutter、AngularDart和一般Dart程式。
複製程式碼
- 使用
我們可以在pub.dartlang.org/上面查詢我們想要用的軟體包,例如protobuf:
在搜尋結果頁,找到我們想要的包:
使用的時候只要將包名和版本號加入到工程的pubspec.yaml
裡:
dependencies:
protobuf: ^0.10.4
複製程式碼
並執行命令列安裝包:
$ flutter packages get
複製程式碼
就可以在工程使用了。說完使用,那如何將我們自己的Flutter Plugin的包提供給別人使用呢?就需要我們將包上傳到Pub。
- 上傳
將一個包上傳到Pub,需要三個步驟:
-
確保
pubspec.yaml
裡面的相關配置填寫正確,README.md
和CHANGELOG.md
最好也補充完整。 -
在上傳前,先執行dry-run命令檢視是否所有內容可以通過檢測
$ flutter pacakges pub publish --dry-run
複製程式碼
3.上傳
$ flutter packages pub publish
複製程式碼
上傳成功後,就可以在別的工程裡使用,在pubspec.yaml
裡的dependencies新增,如下:
dependencies:
包名: 版本號
複製程式碼
6.Private Pub
在將自己團隊的庫上傳到Pub中後,還存在一個問題,那就是因為Pub是一個公共倉庫,上傳上去之後所有人都看的到,這樣就非常不好,因為團隊內的專案是不想讓其他人看到的。這時候我們就需要一個Private Pub,即私有Pub來管理自己團隊的庫。
我在公司內搭建了一個私有Pub,地址為:
******(因為是公司內部地址,就不公佈了)
如果想要使用Private Pub,需要如下的設定:
$ export PUB_HOSTED_URL=******
複製程式碼
設定完成後就可以使用Private Pub了,Pub其他的使用都不變。
7.Flutter 工程結構
最後我們Flutter的工程結構如下:
在Platform Channel中,將獨立的功能都抽取出來打包成plugin,在將多個plugin組合成Flutter的基礎元件,從而快速支援Flutter UI業務程式碼的開發。8.開發流程
最後我們的開發流程如下:
單一功能的Platform Channel以Project的形式存在,經過開發、測試、驗證無誤之後再上傳到Private Pub,不管是純Flutter工程還是Flutter、Native混合工程都可以各取所需,使用需要的Flutter Plugin。
總結
通過分析Flutter的工程結構,我們將Flutter拆分成Platform Channel和Flutter UI兩個相互獨立的模組,明晰了Flutter的工程結構,同時進一步細化Platform Channel,將單一功能的Platform Channel打包成Flutter Plugin,同時搭建自己的私有Pub,方便的管理Flutter Plugin,極大的方便了Flutter的開發,也有利於我們的元件重用和提高開發效率!