現(xiàn)有iOS黎比、Android項(xiàng)目集成Flutter

準(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.png

由于 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 工程的接入就完了舀凛。

ios_demo_s.png

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)了.

android_demo_s.png

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坷虑,歡迎大家留言探討甲馋。

參考文獻(xiàn)

flutter-wiki

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市迄损,隨后出現(xiàn)的幾起案子定躏,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件痊远,死亡現(xiàn)場(chǎng)離奇詭異垮抗,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)碧聪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門冒版,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人逞姿,你說(shuō)我怎么就攤上這事辞嗡。” “怎么了滞造?”我有些...
    開(kāi)封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵续室,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我断部,道長(zhǎng)猎贴,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任蝴光,我火速辦了婚禮她渴,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蔑祟。我一直安慰自己趁耗,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布疆虚。 她就那樣靜靜地躺著苛败,像睡著了一般。 火紅的嫁衣襯著肌膚如雪径簿。 梳的紋絲不亂的頭發(fā)上罢屈,一...
    開(kāi)封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音篇亭,去河邊找鬼缠捌。 笑死,一個(gè)胖子當(dāng)著我的面吹牛译蒂,可吹牛的內(nèi)容都是我干的曼月。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼柔昼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼哑芹!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起捕透,我...
    開(kāi)封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤聪姿,失蹤者是張志新(化名)和其女友劉穎碴萧,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體咳燕,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡勿决,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了招盲。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡嘉冒,死狀恐怖曹货,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情讳推,我是刑警寧澤顶籽,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站银觅,受9級(jí)特大地震影響礼饱,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜究驴,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一镊绪、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧洒忧,春花似錦蝴韭、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至蛉抓,卻和暖如春庆尘,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背巷送。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工驶忌, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人惩系。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓位岔,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親堡牡。 傳聞我的和親對(duì)象是個(gè)殘疾皇子抒抬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

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