<var id="3hzjv"><strike id="3hzjv"><listing id="3hzjv"></listing></strike></var><cite id="3hzjv"></cite>
<cite id="3hzjv"></cite>
<var id="3hzjv"><strike id="3hzjv"><listing id="3hzjv"></listing></strike></var>
<var id="3hzjv"></var><var id="3hzjv"></var>
<cite id="3hzjv"><strike id="3hzjv"><thead id="3hzjv"></thead></strike></cite>
<var id="3hzjv"></var>
<menuitem id="3hzjv"></menuitem>
<var id="3hzjv"></var>
<cite id="3hzjv"></cite>
<var id="3hzjv"></var>
<cite id="3hzjv"><strike id="3hzjv"></strike></cite>
<var id="3hzjv"></var>
<cite id="3hzjv"><video id="3hzjv"><menuitem id="3hzjv"></menuitem></video></cite><var id="3hzjv"><video id="3hzjv"><thead id="3hzjv"></thead></video></var>
<var id="3hzjv"><video id="3hzjv"><listing id="3hzjv"></listing></video></var>
溫馨提示×

如何進行混合開發Flutter

發布時間:2021-09-09 16:23:34 來源:億速云 閱讀:117 作者:柒染 欄目:編程語言

如何進行混合開發Flutter,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。

引言

Flutter 作為 Google 開源的新一代跨平臺、高性能 UI 框架,旨在幫助開發者高效地構建出跨平臺的、UI 與交互體驗一致的精美應用,推出后一直倍受開發者的青睞。

當需要開發一個全新的應用時,我們可以很方便地從零開始,完全使用 Flutter 進行開發。但如果是針對一個現有的應用,需要引入 Flutter 技術,顯然使用 Flutter 全部重寫一遍是不現實的。幸運的是,Flutter 很好地支持了以獨立頁面、甚至是 UI 片段的方式集成到現有的應用中,即所謂的混合開發模式。本文主要從一個 Android 開發的視角,談談 Android 平臺下, Flutter 的混合開發與構建。

Hello Flutter

相信現在應該很少會有移動端開發者不知道 Flutter,這里不再做過多介紹。對于這門技術,使用過的應該絕大多數都會說好;沒用過的推薦嘗試一下,跑個 Demo 體驗體驗,有可能它就是你需要學習和掌握的最后一門新技術了?;剡^頭來,Flutter 究竟有什么獨特的魅力讓它能從一眾技術中脫穎而出呢?總結一下,主要有以下幾點:

  • 跨平臺:可以做到一套代碼完美適配 Android、iOS 平臺,未來還會覆蓋更多平臺,大大節省了開發人力與維護成本,同時擁有出色的跨端 UI 表現一致性。

  • 高效開發:SDK 提供了豐富的 UI 組件,開箱即用;聲明式的 UI 構建方式,大大減少出錯率;Debug 模式提供熱重載能力,可實時預覽代碼變更,不需要重新編譯安裝。

  • 高性能:采用自建渲染引擎,獨立于系統并可單獨優化;區別于 RN、WEEX,沒有中間層轉換的額外開銷;Release 模式下代碼編譯為 AOT 指令,運行高效。

受益于以上的核心優勢,Flutter 推出后圈了很多移動開發者的粉,各互聯網大廠也紛紛將其作為一項基礎技術進行研究。在 Flutter 初期,其應用場景主要是從 0 構建一個全新 App,對混合開發的支持很不友好。但作為一門跨平臺的技術框架,到底還是需要依賴原生平臺提供的諸多系統能力,此外還有眾多現存原生 App 躍躍欲試,因此在這個需求背景下,混合開發的支持與完善至今已發展得越來越好,下面我們就用一個簡單的示例開始 Android 端的 Flutter 混合開發與構建之旅。

引入 Flutter 模塊

要在一個已有的 Android Project 中使用 Flutter,需要引入一個 Flutter Module。在 Android Studio(需要確保 Flutter 插件已經成功安裝并啟用)中打開現有 Android 工程,通過使用 File > New > New Module… 菜單,我們可以新創建一個 Flutter 模塊或是導入一個外部的 Flutter 模塊。

如何進行混合開發Flutter

這里以最簡單的 Android App 項目為例,導入 Flutter 模塊。在 Flutter 模塊導入成功之后,原工程文件、結構都會發生一些變化,主要有:

  • settings.gradle 文件新增了以下內容。其實就是執行對應 Flutter 模塊下 .android/include_flutter.groovy 腳本文件,該步驟會引入一個名為 Flutter 的 Android Library Module,同時還會引入 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')
  • 項目結構變化,如下圖所示:

如何進行混合開發Flutter

在引入 Flutter 模塊之前,項目中僅有 app 一個 Module;而在引入之后,可以看到除了原有的 app Module 外,Flutter Gradle 插件自動引入了額外幾個子 Module:

  • flutter_module:指代要引入的目標 Flutter Module,不會 apply Android 相關的任何插件,主要是包含 Flutter 相關源碼、資源、依賴等。

  • flutter:為 Flutter Gradle 插件引入的 Android Library Module;主要負責編譯 flutter_module 及其依賴的第三方 Package、Plugin 的 Dart 代碼,以及打包 Flutter 資源等。

  • device_info:為 Flutter Gradle 插件自動引入的 Flutter Android Plugin Library Module,這是因為一開始我在 flutter_module 的 pubspec.yaml 文件中添加了對 device_info 這個插件的依賴。Flutter Gradle 工具會將 flutter_module 依賴到的所有插件其 Android 平臺側的代碼、資源作為一個 Library Module 引入到項目中一起參與構建。如果要查看 flutter_module 引入了哪些 Plugin,可以查看其對應目錄下的 .flutter-plugins 與 .flutter-plugins-dependencies 文件,這兩個文件是執行 flutter pub get 時生成的,記錄了插件的本地文件目錄、依賴信息等。

注意:一個工程不能包含多個 Flutter Module,最多只能引入一個,這是由 Flutter 的 Gradle 插件決定的。

使用 Flutter

完成 Flutter 模塊的引入后,我們再來看看如何使用 Flutter。

添加依賴

首先需要在 App 模塊的build.gradle腳本文件中添加對Flutter工程的依賴,只有這樣 Flutter 模塊才會參與到整個應用的構建中來,我們也才能夠在 App 模塊中調用到 Flutter 提供的 Java 層 API。如下所示:

dependencies {
  implementation project(':flutter')
}

運行 Flutter 頁面

我們可以選擇使用 Activity、Fragment 或者 View 來承載 Flutter 的 UI,這里主要介紹前面兩種方式,并假設flutter_module中已經通過runApp方法渲染了一個widget。

  • 運行 Flutter Activity。使用io.flutter.embedding.android.FlutterActivity類可以很方便的啟動一個 Flutter Activity,當然我們也可以繼承它并擴展自己的邏輯。示例代碼如下:

FlutterActivity 
  .withNewEngine() 
  .build(context) 
  .also { startActivity(it) }
  • 運行 Flutter Fragment??梢允褂肍lutterFragmentActivity或者FlutterFragment來添加 Flutter UI 片段:a. 使用FlutterFragmentActivity可以自動創建并添加一個FlutterFragment;b. 手動創建FlutterFragment后添加到目標 Activity 中。示例代碼如下:

val flutterFragment = FlutterFragment.withNewEngine() 
      .dartEntrypoint(getDartEntrypointFunctionName()) 
      .initialRoute(getInitialRoute()) 
      .appBundlePath(getAppBundlePath()) 
      .flutterShellArgs(FlutterShellArgs.fromIntent(intent)) 
      .handleDeeplinking(shouldHandleDeeplinking()) 
      .renderMode(renderMode) 
      .transparencyMode(transparencyMode) 
      .shouldAttachEngineToActivity(shouldAttachEngineToActivity()) 
      .build<FlutterFragment>() 
fragmentManager 
      .beginTransaction() 
      .add( 
           FRAGMENT_CONTAINER_ID, 
           flutterFragment, 
           TAG_FLUTTER_FRAGMENT 
          ) 
       .commit()
  • 平臺層和 Flutter 層通信。不論是開發 Plugin 還是業務邏輯,平臺層與 Flutter 層通信是必不可少的,為此就需要使用到MethodChannel。平臺層通過MethodChannel請求調用 Flutter 層 API 時,數據在經過打包編碼后,通過 JNI、DartVM 傳到 Flutter 層解碼后使用;待結果計算完成后,又會重新打包編碼,經過 DartVM、JNI 傳回到 Native 層;同理,在 Flutter 層請求調用平臺層的 API 時,數據處理是一致的,只是流轉方向相反。通過這種方式,平臺層與 Flutter 層就建立了一個雙向的、異步的通信通道。在下面的示例代碼中,Native 層使用dev.flutter.example/counter創建一個MethodChannel,并設置 Handler 接收 Dart 的遠程方法調用 incrementCounter,并調用 reportCounter 將結果回傳。

channel = MethodChannel(flutterEngine.dartExecutor, "dev.flutter.example/counter") 
channel.setMethodCallHandler { call, _ -> 
     when (call.method) { 
         "incrementCounter" -> { 
              count++ 
              channel.invokeMethod("reportCounter", count) 
         } 
     } 
}

Dart 層使用相同的名稱創建 MethodChannel,并設置 Handler 處理回調結果,隨后調用 incrementCounter 方法請求 counter。示例代碼如下:

final _channel = MethodChannel('dev.flutter.example/counter'); 
_channel.setMethodCallHandler(_handleMessage); 
_channel.invokeMethod('incrementCounter'); 
 
Future<dynamic> _handleMessage(MethodCall call) async { 
    if (call.method == 'reportCounter') { 
      _count = call.arguments as int; 
      notifyListeners(); 
    } 
  }

這里我們是通過手動創建 MethodChannel 進行通信的,這在進行簡單通信的場景是沒問題的,但在通信接口 API 比較復雜的情況就不是很適用了。

一是繁瑣,因為我們需要手寫大量的打包、拆包代碼;二是容易出錯。這個時候就輪到 Pigeon 大顯身手了。Pigeon 是一個官方推出的代碼生成工具,可以生成類型安全的雙向通信 API 接口,具體可以參考官方的 Example,這里不再贅述。

Pigeon :https://flutter.dev/docs/development/platform-integration/platform-channels#pigeon

Flutter APK 解析

到這里,我們已經了解了如何在現有 Android 項目中引入并使用 Flutter,接下來我們再來探究一下 Flutter APK 的結構,看看 Flutter Tools 在這個 APK 包內到底打包了哪些東西。下面兩圖分別為 Debub 模式和 Release 模式下構建出來的 Flutter APK 包結構,忽略了非 Flutter 相關的項。

如何進行混合開發Flutter

可以看到兩個模式下的 APK 結構大致相同,說明如下:

  • lib/{arch}/libflutter.so:為對應架構的 Flutter Engine 共享庫,負責 Flutter 渲染、JNI 通信、DartVM。如果不需要對應架構的版本,通過 abiFilters 可以 Exclude 掉。

  • lib/{arch}/libapp.so:只存在于 Release 模式下,共享庫中包含 Dart AOT 生成的二進制指令和數據。在運行時,Flutter Engine 通過 Dynamic Load 的方式,從共享庫中讀取對應的可執行機器指令以及數據。

  • assets/flutter_assets:Flutter 引用到的相關資源

    • fonts:包含字體庫。

  • FontManifest.json:引用到的字體庫清單文件,json 格式,所有使用到的字體、以及字體文件在 flutter_assets 下的路徑。

  • AssetManifest.json:其他資源清單文件,json 格式,為所有資源名稱到資源路徑的映射,Flutter 在加載某一項資源時,會通過這個配置清單找到對應路徑的資源進行讀取后加載。

  • kernel_blob.bin、isolate_snapshot_data、vm_snapshot_data:只存在于 Debug 模式下,分別為 DartVM 字節碼與數據,其作用類似于 libapp.so,只是存在形式、打包方式不同。在 Debug 模式下,Flutter Tools 將指令和數據分別打包,主要是為了熱重載(HotReload)服務的,而在 Release 模式下是統一打包成共享庫。

看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

免費撥打  400 100 2938 免費撥打 400 100 2938
24小時售后技術支持 24小時售后技術支持
返回頂部 返回頂部