準(zhǔn)備工作
首先斩郎,我們分別用 Xcode 與 Android Studio 快速建立一個(gè)只有首頁(yè)的基本工程,工程名分別為 iOSDemo 與 AndroidDemo.
這時(shí)疮装,Android 工程就已經(jīng)準(zhǔn)備好了缘琅;而對(duì)于 iOS 工程來(lái)說(shuō),由于基本工程并不支持以組件化的方式管理項(xiàng)目廓推,因此我們還需要多做一步刷袍,將其改造成使用 CocoaPods 管理的工程,也就是要在 iOSDemo 根目錄下創(chuàng)建一個(gè)只有基本信息的 Podfile 文件:
target 'iOSDemo' do
use_frameworks!
target 'iOSDemoTests' do
inherit! :search_paths
end
target 'iOSDemoUITests' do
end
end
然后樊展,在命令行輸入 pod install 后呻纹,會(huì)自動(dòng)生成一個(gè) iOSDemo.xcworkspace 文件堆生,這時(shí)我們就完成了 iOS 工程改造。
Flutter 混編方案介紹
如果你想要在已有的原生 App 里嵌入一些 Flutter 頁(yè)面雷酪,有兩個(gè)辦法:
- 將原生工程作為 Flutter 工程的子工程淑仆,由 Flutter 統(tǒng)一管理。這種模式哥力,就是統(tǒng)一管理模式蔗怠。
- 將 Flutter 工程作為原生工程共用的子模塊,維持原有的原生工程管理方式不變吩跋。這種模式寞射,就是三端分離模式。
由于 Flutter 早期提供的混編方式能力及相關(guān)資料有限锌钮,國(guó)內(nèi)較早使用 Flutter 混合開(kāi)發(fā)的團(tuán)隊(duì)大多使用的是統(tǒng)一管理模式桥温。
但是,隨著功能迭代的深入梁丘,這種方案的弊端也隨之顯露侵浸,不僅三端(Android、iOS兰吟、Flutter)代碼耦合嚴(yán)重通惫,相關(guān)工具鏈耗時(shí)也隨之大幅增長(zhǎng),導(dǎo)致開(kāi)發(fā)效率降低混蔼。
所以履腋,后續(xù)使用 Flutter 混合開(kāi)發(fā)的團(tuán)隊(duì)陸續(xù)按照三端代碼分離的模式來(lái)進(jìn)行依賴治理,實(shí)現(xiàn)了 Flutter 工程的輕量級(jí)接入惭嚣。
輕量級(jí)接入遵湖,三端代碼分離模式把 Flutter 模塊作為原生工程的子模塊,還可以快速實(shí)現(xiàn) Flutter 功能的解除依賴晚吞,降低原生工程的改造成本延旧。而 Flutter 工程通過(guò) Android Studio 進(jìn)行管理,無(wú)需打開(kāi)原生工程槽地,可直接進(jìn)行 Dart 代碼和原生代碼的開(kāi)發(fā)調(diào)試迁沫。
三端工程分離模式的關(guān)鍵是抽離 Flutter 工程,將不同平臺(tái)的構(gòu)建產(chǎn)物依照標(biāo)準(zhǔn)組件化的形式進(jìn)行管理捌蚊,即 Android 使用 aar集畅、iOS 使用 pod。也就是可以像引用其他第三方原生組件庫(kù)那樣快速接入 Flutter 缅糟。
集成 Flutter
原生工程對(duì) Flutter 的依賴主要分為兩部分:
- Flutter 庫(kù)和引擎挺智,也就是 Flutter 的 Framework 庫(kù)和引擎庫(kù)。
- Flutter 工程窗宦,也就是我們自己實(shí)現(xiàn)的 Flutter 模塊功能赦颇,主要包括 Flutter 工程 lib 目錄下的 Dart 代碼實(shí)現(xiàn)的這部分功能二鳄。
創(chuàng)建同級(jí)目錄的Flutter module
Flutter create -t module flutter_demo
然后我們分別對(duì) flutter_demo 進(jìn)行集成
iOS 模塊集成
先說(shuō)一下官方集成Flutter方式 wiki,里面用的兩個(gè)腳本 podhelper.rb 和xcode_backend.sh 分別在Podfile和Build Phases里面
flutter_application_path = '../flutter_demo/'
eval(File.read(File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')), binding)
"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" build
"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" embed
解釋下這兩個(gè)腳本的作用:
1.podhelper.rb
- 通過(guò)Pod引入Flutter.framework(Flutter引擎)媒怯,以及Flutter的插件注冊(cè)表FlutterPluginRegistrant(創(chuàng)建的工程中GeneratedPluginRegistrant.{h,m}文件中)
- 引入.flutter-plugins的依賴
- 導(dǎo)入Generated.xcconfig配置订讼,這里面放的是Flutter要用的環(huán)境變量(如:xcode_backend.sh開(kāi)頭就要用的$FLUTTER_ROOT)
2.xcode_backend.sh
這個(gè)腳本原本是放在Build Phases,在Debug和Release模式下分別會(huì)產(chǎn)出對(duì)應(yīng)環(huán)境的Flutter產(chǎn)物(Flutter有Debug沪摄,Profile躯嫉,Release三個(gè)模式)。并且里面還有一句代碼是:
RunCommand cp -r -- "${app_framework}" "${derived_dir}"
- 在Debug和Release下構(gòu)建出對(duì)應(yīng)的Flutter產(chǎn)物杨拐,App.framework祈餐,flutter_assets(App.framework就是我們?cè)趌ib下面寫的Dart代碼,flutter_assets就是我們資源)把上面的產(chǎn)物拷貝到App包里
在 iOS 平臺(tái)哄陶,原生工程對(duì) Flutter 的依賴分別是:
- Flutter 庫(kù)和引擎帆阳,即 Flutter.framework;
- Flutter 工程的產(chǎn)物屋吨,即 App.framework蜒谤。
iOS 平臺(tái)的對(duì) Flutter 模塊依賴,實(shí)際上就是通過(guò)打包命令生成這兩個(gè)產(chǎn)物至扰,我們將它們封裝成一個(gè) pod 供原生工程引用鳍徽,這里我們解除對(duì)Flutter工程的依賴,podhelper.rb敢课,xcode_backend.sh腳本我們不使用阶祭。
Flutter build ios --debug
這條命令的作用是編譯 Flutter 工程生成兩個(gè)產(chǎn)物:Flutter.framework 和 App.framework。如果需要release直秆,把 debug 換成 release 就可以構(gòu)建 release 產(chǎn)物.
接下來(lái)濒募,我們讓iOSDemo依賴Flutter的編譯的這兩個(gè)產(chǎn)物,這里使用cocoapods進(jìn)行依賴:
我們?cè)?flutter_demo/.ios/Flutter目錄創(chuàng)建FlutterEngine.podspec文件(路徑可以修改成想要的位置)
pod spec create FlutterEngine
編輯FlutterEngine.podspec 文件依賴 Flutter.framework 和 App.framework
Pod::Spec.new do |spec|
spec.name = "FlutterEngine"
spec.version = "0.0.1"
spec.summary = "A short description of FlutterEngine."
spec.description = <<-DESC
A short description of FlutterEngine.
DESC
spec.homepage = 'https://github.com/xx/FlutterEngine'
spec.license = { :type => 'MIT', :file => 'LICENSE' }
spec.author = { "tema.tian" => "temagsoft@163.com" }
spec.source = { :git => "", :tag => "#{spec.version}" }
spec.ios.deployment_target = '8.0'
spec.ios.vendored_frameworks = "App.framework", "engine/Flutter.framework"
end
pod lib lint 一下 Flutter組件模塊就做好了圾结,我們?cè)傩薷囊幌耰OSDemo的 Podfile,把它集成進(jìn)去
target 'iOSDemo' do
use_frameworks!
pod 'FlutterEngine', :path => '../flutter_demo/.ios/Flutter/'
target 'iOSDemoTests' do
inherit! :search_paths
end
target 'iOSDemoUITests' do
end
end
pod install 一下瑰剃,F(xiàn)lutter 模塊就集成進(jìn) iOS 原生工程中了。
我們?cè)谛薷囊幌耰OSDemo AppDelegate 把window的rootViewController 設(shè)置為 FlutterViewController
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
let flutterVC = FlutterViewController()
flutterVC.setInitialRoute("defaultRoute")
window?.rootViewController = flutterVC
window?.makeKeyAndVisible()
return true
}
點(diǎn)擊xcode運(yùn)行筝野,最后點(diǎn)擊運(yùn)行晌姚,官方的 Flutter Widget 也展示出來(lái)了。至此歇竟,iOS 工程的接入就完了舀凛。
Android 模塊集成
Android 原生工程對(duì) Flutter 的依賴主要分為兩部分,對(duì)應(yīng)到 Android 平臺(tái)途蒋,這兩部分分別是:
- Flutter 庫(kù)和引擎,也就是 icudtl.dat馋记、libFlutter.so号坡,還有一些 class 文件懊烤。這些文件都封裝在 Flutter.jar 中。
- Flutter 工程產(chǎn)物宽堆,主要包括應(yīng)用程序數(shù)據(jù)段 isolate_snapshot_data腌紧、應(yīng)用程序指令段 isolate_snapshot_instr、虛擬機(jī)數(shù)據(jù)段 vm_snapshot_data畜隶、虛擬機(jī)指令段 vm_snapshot_instr壁肋、資源文件 Flutter_assets。
我們對(duì) Android 的 Flutter 依賴進(jìn)行抽取籽慢,首先我們?cè)賔lutter_demo根目錄浸遗,執(zhí)行arr打包命令
Flutter build apk --debug
如果需要release,把 debug 換成 release 就可以構(gòu)建 release 產(chǎn)物.
打包構(gòu)建的flutter-debug.arr 位于 /.android/Flutter/build/outputs/aar/目錄下箱亿,我們把它拷貝到AndroidDemo的App/libs目錄下跛锌,然后在build.gradle中對(duì)他添加依賴:
implementation(name: 'flutter-debug', ext: 'aar')
sync同步一下,然后我們修改AndroidDemo MainActivity的代碼届惋,將setContentView的加載View換成FlutterView
View FlutterView = Flutter.createView(this, getLifecycle(), "defaultRoute");
setContentView(FlutterView);
最后點(diǎn)擊運(yùn)行髓帽, Flutter Widget 就展示出來(lái)了.
IOS,Android 集成這里是手動(dòng)拷貝pod, aar脑豹,多人維護(hù)很麻煩郑藏,可以本地測(cè)試用debug包,提交用release包瘩欺,或者把a(bǔ)ar/pod以版本的方式發(fā)布到私有Maven/Cocoapod必盖,以組件名+版本的方式在工程中引用,不直接管理打包構(gòu)建產(chǎn)物击碗。
對(duì)于三端工程分離模式最主要的則是抽離 Flutter 工程筑悴,將不同平臺(tái)的構(gòu)建產(chǎn)物依照標(biāo)準(zhǔn)組件化的形式進(jìn)行管理,即:針對(duì) Android 平臺(tái)打包構(gòu)建生成 aar稍途,通過(guò) build.gradle 進(jìn)行依賴管理阁吝;針對(duì) iOS 平臺(tái)打包構(gòu)建生成 framework,將其封裝成獨(dú)立的 pod械拍,并通過(guò) podfile 進(jìn)行依賴管理突勇。
至此原生集成Flutter就分享完了,附上demo坷虑,歡迎大家留言探討甲馋。