十年網(wǎng)站開發(fā)經(jīng)驗(yàn) + 多家企業(yè)客戶 + 靠譜的建站團(tuán)隊(duì)
量身定制 + 運(yùn)營(yíng)維護(hù)+專業(yè)推廣+無(wú)憂售后,網(wǎng)站問(wèn)題一站解決
如何進(jìn)行混合開發(fā)Flutter,很多新手對(duì)此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來(lái)學(xué)習(xí)下,希望你能有所收獲。
公司主營(yíng)業(yè)務(wù):網(wǎng)站設(shè)計(jì)制作、網(wǎng)站設(shè)計(jì)、移動(dòng)網(wǎng)站開發(fā)等業(yè)務(wù)。幫助企業(yè)客戶真正實(shí)現(xiàn)互聯(lián)網(wǎng)宣傳,提高企業(yè)的競(jìng)爭(zhēng)能力。成都創(chuàng)新互聯(lián)是一支青春激揚(yáng)、勤奮敬業(yè)、活力青春激揚(yáng)、勤奮敬業(yè)、活力澎湃、和諧高效的團(tuán)隊(duì)。公司秉承以“開放、自由、嚴(yán)謹(jǐn)、自律”為核心的企業(yè)文化,感謝他們對(duì)我們的高要求,感謝他們從不同領(lǐng)域給我們帶來(lái)的挑戰(zhàn),讓我們激情的團(tuán)隊(duì)有機(jī)會(huì)用頭腦與智慧不斷的給客戶帶來(lái)驚喜。成都創(chuàng)新互聯(lián)推出清徐免費(fèi)做網(wǎng)站回饋大家。
Flutter 作為 Google 開源的新一代跨平臺(tái)、高性能 UI 框架,旨在幫助開發(fā)者高效地構(gòu)建出跨平臺(tái)的、UI 與交互體驗(yàn)一致的精美應(yīng)用,推出后一直倍受開發(fā)者的青睞。
當(dāng)需要開發(fā)一個(gè)全新的應(yīng)用時(shí),我們可以很方便地從零開始,完全使用 Flutter 進(jìn)行開發(fā)。但如果是針對(duì)一個(gè)現(xiàn)有的應(yīng)用,需要引入 Flutter 技術(shù),顯然使用 Flutter 全部重寫一遍是不現(xiàn)實(shí)的。幸運(yùn)的是,F(xiàn)lutter 很好地支持了以獨(dú)立頁(yè)面、甚至是 UI 片段的方式集成到現(xiàn)有的應(yīng)用中,即所謂的混合開發(fā)模式。本文主要從一個(gè) Android 開發(fā)的視角,談?wù)?Android 平臺(tái)下, Flutter 的混合開發(fā)與構(gòu)建。
相信現(xiàn)在應(yīng)該很少會(huì)有移動(dòng)端開發(fā)者不知道 Flutter,這里不再做過(guò)多介紹。對(duì)于這門技術(shù),使用過(guò)的應(yīng)該絕大多數(shù)都會(huì)說(shuō)好;沒(méi)用過(guò)的推薦嘗試一下,跑個(gè) Demo 體驗(yàn)體驗(yàn),有可能它就是你需要學(xué)習(xí)和掌握的最后一門新技術(shù)了。回過(guò)頭來(lái),F(xiàn)lutter 究竟有什么獨(dú)特的魅力讓它能從一眾技術(shù)中脫穎而出呢?總結(jié)一下,主要有以下幾點(diǎn):
跨平臺(tái):可以做到一套代碼完美適配 Android、iOS 平臺(tái),未來(lái)還會(huì)覆蓋更多平臺(tái),大大節(jié)省了開發(fā)人力與維護(hù)成本,同時(shí)擁有出色的跨端 UI 表現(xiàn)一致性。
高效開發(fā):SDK 提供了豐富的 UI 組件,開箱即用;聲明式的 UI 構(gòu)建方式,大大減少出錯(cuò)率;Debug 模式提供熱重載能力,可實(shí)時(shí)預(yù)覽代碼變更,不需要重新編譯安裝。
高性能:采用自建渲染引擎,獨(dú)立于系統(tǒng)并可單獨(dú)優(yōu)化;區(qū)別于 RN、WEEX,沒(méi)有中間層轉(zhuǎn)換的額外開銷;Release 模式下代碼編譯為 AOT 指令,運(yùn)行高效。
受益于以上的核心優(yōu)勢(shì),F(xiàn)lutter 推出后圈了很多移動(dòng)開發(fā)者的粉,各互聯(lián)網(wǎng)大廠也紛紛將其作為一項(xiàng)基礎(chǔ)技術(shù)進(jìn)行研究。在 Flutter 初期,其應(yīng)用場(chǎng)景主要是從 0 構(gòu)建一個(gè)全新 App,對(duì)混合開發(fā)的支持很不友好。但作為一門跨平臺(tái)的技術(shù)框架,到底還是需要依賴原生平臺(tái)提供的諸多系統(tǒng)能力,此外還有眾多現(xiàn)存原生 App 躍躍欲試,因此在這個(gè)需求背景下,混合開發(fā)的支持與完善至今已發(fā)展得越來(lái)越好,下面我們就用一個(gè)簡(jiǎn)單的示例開始 Android 端的 Flutter 混合開發(fā)與構(gòu)建之旅。
要在一個(gè)已有的 Android Project 中使用 Flutter,需要引入一個(gè) Flutter Module。在 Android Studio(需要確保 Flutter 插件已經(jīng)成功安裝并啟用)中打開現(xiàn)有 Android 工程,通過(guò)使用 File > New > New Module… 菜單,我們可以新創(chuàng)建一個(gè) Flutter 模塊或是導(dǎo)入一個(gè)外部的 Flutter 模塊。
這里以最簡(jiǎn)單的 Android App 項(xiàng)目為例,導(dǎo)入 Flutter 模塊。在 Flutter 模塊導(dǎo)入成功之后,原工程文件、結(jié)構(gòu)都會(huì)發(fā)生一些變化,主要有:
settings.gradle 文件新增了以下內(nèi)容。其實(shí)就是執(zhí)行對(duì)應(yīng) Flutter 模塊下 .android/include_flutter.groovy 腳本文件,該步驟會(huì)引入一個(gè)名為 Flutter 的 Android Library Module,同時(shí)還會(huì)引入 Flutter 模塊所依賴的所有插件。
setBinding(new Binding([gradle: this])) evaluate(new File( settingsDir.parentFile, 'flutter_module/.android/include_flutter.groovy' )) include ':flutter_module' project(':flutter_module').projectDir = new File('../flutter_module')
項(xiàng)目結(jié)構(gòu)變化,如下圖所示:
在引入 Flutter 模塊之前,項(xiàng)目中僅有 app 一個(gè) Module;而在引入之后,可以看到除了原有的 app Module 外,F(xiàn)lutter Gradle 插件自動(dòng)引入了額外幾個(gè)子 Module:
flutter_module:指代要引入的目標(biāo) Flutter Module,不會(huì) apply Android 相關(guān)的任何插件,主要是包含 Flutter 相關(guān)源碼、資源、依賴等。
flutter:為 Flutter Gradle 插件引入的 Android Library Module;主要負(fù)責(zé)編譯 flutter_module 及其依賴的第三方 Package、Plugin 的 Dart 代碼,以及打包 Flutter 資源等。
device_info:為 Flutter Gradle 插件自動(dòng)引入的 Flutter Android Plugin Library Module,這是因?yàn)橐婚_始我在 flutter_module 的 pubspec.yaml 文件中添加了對(duì) device_info 這個(gè)插件的依賴。Flutter Gradle 工具會(huì)將 flutter_module 依賴到的所有插件其 Android 平臺(tái)側(cè)的代碼、資源作為一個(gè) Library Module 引入到項(xiàng)目中一起參與構(gòu)建。如果要查看 flutter_module 引入了哪些 Plugin,可以查看其對(duì)應(yīng)目錄下的 .flutter-plugins 與 .flutter-plugins-dependencies 文件,這兩個(gè)文件是執(zhí)行 flutter pub get 時(shí)生成的,記錄了插件的本地文件目錄、依賴信息等。
注意:一個(gè)工程不能包含多個(gè) Flutter Module,最多只能引入一個(gè),這是由 Flutter 的 Gradle 插件決定的。
完成 Flutter 模塊的引入后,我們?cè)賮?lái)看看如何使用 Flutter。
首先需要在 App 模塊的build.gradle腳本文件中添加對(duì)Flutter工程的依賴,只有這樣 Flutter 模塊才會(huì)參與到整個(gè)應(yīng)用的構(gòu)建中來(lái),我們也才能夠在 App 模塊中調(diào)用到 Flutter 提供的 Java 層 API。如下所示:
dependencies { implementation project(':flutter') }
我們可以選擇使用 Activity、Fragment 或者 View 來(lái)承載 Flutter 的 UI,這里主要介紹前面兩種方式,并假設(shè)flutter_module中已經(jīng)通過(guò)runApp方法渲染了一個(gè)widget。
運(yùn)行 Flutter Activity。使用io.flutter.embedding.android.FlutterActivity類可以很方便的啟動(dòng)一個(gè) Flutter Activity,當(dāng)然我們也可以繼承它并擴(kuò)展自己的邏輯。示例代碼如下:
FlutterActivity .withNewEngine() .build(context) .also { startActivity(it) }
運(yùn)行 Flutter Fragment??梢允褂肍lutterFragmentActivity或者FlutterFragment來(lái)添加 Flutter UI 片段:a. 使用FlutterFragmentActivity可以自動(dòng)創(chuàng)建并添加一個(gè)FlutterFragment;b. 手動(dòng)創(chuàng)建FlutterFragment后添加到目標(biāo) Activity 中。示例代碼如下:
val flutterFragment = FlutterFragment.withNewEngine() .dartEntrypoint(getDartEntrypointFunctionName()) .initialRoute(getInitialRoute()) .appBundlePath(getAppBundlePath()) .flutterShellArgs(FlutterShellArgs.fromIntent(intent)) .handleDeeplinking(shouldHandleDeeplinking()) .renderMode(renderMode) .transparencyMode(transparencyMode) .shouldAttachEngineToActivity(shouldAttachEngineToActivity()) .build() fragmentManager .beginTransaction() .add( FRAGMENT_CONTAINER_ID, flutterFragment, TAG_FLUTTER_FRAGMENT ) .commit()
平臺(tái)層和 Flutter 層通信。不論是開發(fā) Plugin 還是業(yè)務(wù)邏輯,平臺(tái)層與 Flutter 層通信是必不可少的,為此就需要使用到MethodChannel。平臺(tái)層通過(guò)MethodChannel請(qǐng)求調(diào)用 Flutter 層 API 時(shí),數(shù)據(jù)在經(jīng)過(guò)打包編碼后,通過(guò) JNI、DartVM 傳到 Flutter 層解碼后使用;待結(jié)果計(jì)算完成后,又會(huì)重新打包編碼,經(jīng)過(guò) DartVM、JNI 傳回到 Native 層;同理,在 Flutter 層請(qǐng)求調(diào)用平臺(tái)層的 API 時(shí),數(shù)據(jù)處理是一致的,只是流轉(zhuǎn)方向相反。通過(guò)這種方式,平臺(tái)層與 Flutter 層就建立了一個(gè)雙向的、異步的通信通道。在下面的示例代碼中,Native 層使用dev.flutter.example/counter創(chuàng)建一個(gè)MethodChannel,并設(shè)置 Handler 接收 Dart 的遠(yuǎn)程方法調(diào)用 incrementCounter,并調(diào)用 reportCounter 將結(jié)果回傳。
channel = MethodChannel(flutterEngine.dartExecutor, "dev.flutter.example/counter") channel.setMethodCallHandler { call, _ -> when (call.method) { "incrementCounter" -> { count++ channel.invokeMethod("reportCounter", count) } } }
Dart 層使用相同的名稱創(chuàng)建 MethodChannel,并設(shè)置 Handler 處理回調(diào)結(jié)果,隨后調(diào)用 incrementCounter 方法請(qǐng)求 counter。示例代碼如下:
final _channel = MethodChannel('dev.flutter.example/counter'); _channel.setMethodCallHandler(_handleMessage); _channel.invokeMethod('incrementCounter'); Future_handleMessage(MethodCall call) async { if (call.method == 'reportCounter') { _count = call.arguments as int; notifyListeners(); } }
這里我們是通過(guò)手動(dòng)創(chuàng)建 MethodChannel 進(jìn)行通信的,這在進(jìn)行簡(jiǎn)單通信的場(chǎng)景是沒(méi)問(wèn)題的,但在通信接口 API 比較復(fù)雜的情況就不是很適用了。
一是繁瑣,因?yàn)槲覀冃枰謱懘罅康拇虬?、拆包代碼;二是容易出錯(cuò)。這個(gè)時(shí)候就輪到 Pigeon 大顯身手了。Pigeon 是一個(gè)官方推出的代碼生成工具,可以生成類型安全的雙向通信 API 接口,具體可以參考官方的 Example,這里不再贅述。
Pigeon :https://flutter.dev/docs/development/platform-integration/platform-channels#pigeon
到這里,我們已經(jīng)了解了如何在現(xiàn)有 Android 項(xiàng)目中引入并使用 Flutter,接下來(lái)我們?cè)賮?lái)探究一下 Flutter APK 的結(jié)構(gòu),看看 Flutter Tools 在這個(gè) APK 包內(nèi)到底打包了哪些東西。下面兩圖分別為 Debub 模式和 Release 模式下構(gòu)建出來(lái)的 Flutter APK 包結(jié)構(gòu),忽略了非 Flutter 相關(guān)的項(xiàng)。
可以看到兩個(gè)模式下的 APK 結(jié)構(gòu)大致相同,說(shuō)明如下:
lib/{arch}/libflutter.so:為對(duì)應(yīng)架構(gòu)的 Flutter Engine 共享庫(kù),負(fù)責(zé) Flutter 渲染、JNI 通信、DartVM。如果不需要對(duì)應(yīng)架構(gòu)的版本,通過(guò) abiFilters 可以 Exclude 掉。
lib/{arch}/libapp.so:只存在于 Release 模式下,共享庫(kù)中包含 Dart AOT 生成的二進(jìn)制指令和數(shù)據(jù)。在運(yùn)行時(shí),F(xiàn)lutter Engine 通過(guò) Dynamic Load 的方式,從共享庫(kù)中讀取對(duì)應(yīng)的可執(zhí)行機(jī)器指令以及數(shù)據(jù)。
assets/flutter_assets:Flutter 引用到的相關(guān)資源
fonts:包含字體庫(kù)。
FontManifest.json:引用到的字體庫(kù)清單文件,json 格式,所有使用到的字體、以及字體文件在 flutter_assets 下的路徑。
AssetManifest.json:其他資源清單文件,json 格式,為所有資源名稱到資源路徑的映射,F(xiàn)lutter 在加載某一項(xiàng)資源時(shí),會(huì)通過(guò)這個(gè)配置清單找到對(duì)應(yīng)路徑的資源進(jìn)行讀取后加載。
kernel_blob.bin、isolate_snapshot_data、vm_snapshot_data:只存在于 Debug 模式下,分別為 DartVM 字節(jié)碼與數(shù)據(jù),其作用類似于 libapp.so,只是存在形式、打包方式不同。在 Debug 模式下,F(xiàn)lutter Tools 將指令和數(shù)據(jù)分別打包,主要是為了熱重載(HotReload)服務(wù)的,而在 Release 模式下是統(tǒng)一打包成共享庫(kù)。
看完上述內(nèi)容是否對(duì)您有幫助呢?如果還想對(duì)相關(guān)知識(shí)有進(jìn)一步的了解或閱讀更多相關(guān)文章,請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝您對(duì)創(chuàng)新互聯(lián)的支持。