flutter打包的app有多大_Flutter原生混合开发
使用 Flutter 從頭開始寫一個 App是一件輕松愜意的事情。但是對于成熟產品來說,完全摒棄原有 App 的歷史沉淀,全面轉向 Flutter 并不現實。用 Flutter 去統一 iOS/Android 技術棧,把它作為已有原生 App 的擴展,然后通過逐步試驗有序推進從而提升終端開發效率,可能才是現階段 Flutter 最有效的集成方式。
那么,Flutter 工程與原生工程該如何組織管理?不同平臺的 Flutter 工程打包構建產物該如何抽取封裝?封裝后的產物該如何引入原生工程?原生工程又該如何使用封裝后的 Flutter 能力?
這些問題使得在已有原生 App 中接入 Flutter 看似并不是一件容易的事情。那接下來,我就和你介紹下如何在原生 App 中以最自然的方式接入 Flutter。
準備工作
既然要在原生應用中混編 Flutter,相信你一定已經準備好了原生應用工程。如果你還沒有準備好也沒關系,我會以一個最小化的示例和你演示這個改造過程。
首先,我們分別用 Xcode 與 Android Studio 快速建立一個只有首頁的基本工程,工程名分別為 iOSDemo 與 AndroidDemo。
到此,Android 工程就已經準備好了;而對于 iOS 工程來說,由于基本工程并不支持以組件化的方式管理項目,因此我們還需要多做一步,將其改造成使用 CocoaPods 管理的工程,也就是要在 iOSDemo 根目錄下創建一個只有基本信息的 Podfile 文件。Podfile文件的配置如下:
use_frameworks! platform :ios, '8.0' target 'iOSDemo' do #todo end然后,在命令行輸入 pod install 命令后,會自動生成一個 iOSDemo.xcworkspace 文件,該文件存放的就是我們項目需要的依賴庫,這時我們就完成了 iOS 工程改造。
混編方案
如果你想要在已有的原生 App 里嵌入一些 Flutter 頁面,有兩個辦法可以實現,即統一管理模式和三端分離模式。 - 將原生工程作為 Flutter 工程的子工程,由 Flutter 統一管理。這種模式,就是統一管理模式。 - 將 Flutter 工程作為原生工程共用的子模塊,維持原有的原生工程管理方式不變。這種模式,就是三端分離模式。
由于 Flutter 早期提供的混編方式能力及相關資料有限,國內較早使用 Flutter 混合開發的團隊大多使用的是統一管理模式。但是,隨著功能迭代的深入,這種方案的弊端也隨之顯露,不僅三端(Android、iOS、Flutter)代碼耦合嚴重,相關工具鏈耗時也隨之大幅增長,導致開發效率降低。
所以,后續使用 Flutter 混合開發的團隊陸續按照三端代碼分離的模式來進行依賴治理,實現了 Flutter 工程的輕量級接入。
除此之外,三端代碼分離模式還可以把 Flutter 模塊作為原生工程的子模塊,從而快速實現 Flutter 功能的“熱插拔”,降低原生工程改造的成本。而 Flutter 工程通過 Android Studio 進行管理,無需打開原生工程,可直接進行 Dart 代碼和原生代碼的開發調試。
三端工程分離模式的關鍵是抽離 Flutter 工程,將不同平臺的構建產物依照標準組件化的形式進行管理,即 Android 使用 aar、iOS 使用 pod。換句話說,接下來介紹的混編方案會將 Flutter 模塊打包成 aar 和 pod,這樣原生工程就可以像引用其他第三方原生組件庫那樣快速接入 Flutter 了。
集成Flutter準備
當我們創建一個新的Flutter 工程時,除了一些通用配置外,Flutter還包括 Flutter 工程和原生工程的目錄(即 iOS 和 Android 兩個目錄)。在這種情況下,原生工程就會依賴于 Flutter 相關的庫和資源,從而無法脫離父目錄進行獨立構建和運行。
原生工程對 Flutter 的依賴主要分為兩部分: - Flutter 庫和引擎,也就是 Flutter 的 Framework 庫和引擎庫; - Flutter 工程,也就是我們自己實現的 Flutter 模塊功能,主要包括 Flutter 工程 lib 目錄下的 Dart 代碼實現的這部分功能。
在已經有原生工程的情況下,我們需要在同級目錄創建 Flutter 模塊,構建 iOS 和 Android 各自的 Flutter 依賴庫。這也很好實現,Flutter 就為我們提供了這樣的命令。我們只需要在原生項目的同級目錄下,執行 Flutter 命令創建名為 flutter_library 的模塊即可,命令如下。
Flutter create -t module flutter_library這里的 Flutter 模塊,也是 Flutter 工程,我們用 Android Studio 打開它,其目錄如下圖所示。
可以看到,和傳統的 Flutter 工程相比,Flutter 模塊工程也有內嵌的 Android 工程與 iOS 工程,因此我們可以像普通工程一樣使用 Android Studio 進行開發調試。
仔細查看可以發現,Flutter 模塊有一個細微的變化:Android 工程下多了一個 Flutter 目錄,這個目錄下的 build.gradle 配置就是我們構建 aar 的打包配置。這就是模塊工程既能像 Flutter 傳統工程一樣使用 Android Studio 開發調試,又能打包構建 aar 與 pod 的秘密。
實際上,iOS 工程的目錄結構也有細微變化,但這個差異并不影響打包構建,因此此處就不再展開了。
然后,我們打開 main.dart 文件,將其邏輯更新為以下代碼邏輯,即一個寫著“Hello from Flutter”的全屏紅色的 Flutter Widget,如下所示。
import 'package:flutter/material.dart'; import 'dart:ui';void main() => runApp(_widgetForRoute(window.defaultRouteName));//獨立運行傳入默認路由Widget _widgetForRoute(String route) {switch (route) {default:return MaterialApp(home: Scaffold(backgroundColor: const Color(0xFFD63031),//ARGB紅色body: Center(child: Text('Hello from Flutter', //顯示的文字textDirection: TextDirection.ltr,style: TextStyle(fontSize: 20.0,color: Colors.blue,),),),),);} }我們創建的 Widget 實際上是包在一個 switch-case 語句中的。這是因為封裝的 Flutter 模塊一般會有多個頁面級 Widget,原生 App 代碼則會通過傳入路由標識字符串,告訴 Flutter 究竟應該返回何種 Widget。為了簡化案例,在這里我們忽略標識字符串,統一返回一個 MaterialApp。
接下來,我們要做的事情就是把這段代碼編譯打包,構建出對應的 Android 和 iOS 依賴庫,實現原生工程的接入。
現在,我們首先來看看 Android 工程如何接入。
Android原生集成
之前我們提到原生工程對 Flutter 的依賴主要分為兩部分,對應到 Android 平臺,這兩部分分別是: - Flutter 庫和引擎,也就是 icudtl.dat、libFlutter.so,還有一些 class 文件。這些文件都封裝在 Flutter.jar 中。 - Flutter 工程產物,主要包括應用程序數據段 isolate_snapshot_data、應用程序指令段 isolate_snapshot_instr、虛擬機數據段 vm_snapshot_data、虛擬機指令段 vm_snapshot_instr和資源文件 Flutter_assets等內容。
搞清楚 Flutter 工程的 Android 編譯產物之后,我們需要對 Android 的 Flutter 依賴進行抽取,步驟如下。
首先,在 Flutter_library 的根目錄下,執行 aar 打包構建命令,如下所示。
Flutter build apk --debug這條命令的作用是編譯工程產物,并將 Flutter.jar 和工程產物編譯結果封裝成一個 aar,如下圖所示。
你很快就會想到,如果是構建 release 產物,只需要把 debug 換成 release 就可以了。
打包構建的 flutter-debug.aar 位于.android/Flutter/build/outputs/aar/ 目錄下,我們把它拷貝到原生 Android 工程 AndroidDemo 的 app/libs 目錄下,并在 App 的打包配置 build.gradle 中添加對它的依賴。
... repositories {flatDir {dirs 'libs' // aar目錄} } android {...compileOptions {sourceCompatibility 1.8 //Java 1.8targetCompatibility 1.8 //Java 1.8}... }dependencies {...implementation(name: 'flutter-debug', ext: 'aar')//Flutter模塊aar... }Sync 一下項目,Flutter 模塊就被添加到了 Android 項目中。
然后,我們試著改一下 MainActivity.java 的代碼,把它的 contentView 改成 Flutter 的 widget,如下所示。
protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);View FlutterView = Flutter.createView(this, getLifecycle(), "defaultRoute"); //傳入路由標識符setContentView(FlutterView);//用FlutterView替代Activity的ContentView }重新運行Android原生工程,效果如下圖。
iOS 原生集成
iOS 工程接入的情況要稍微復雜一些。在 iOS 平臺,原生工程對 Flutter 的依賴分別是: - Flutter 庫和引擎,即 Flutter.framework; - Flutter 工程的產物,即 App.framework。
iOS 平臺的 Flutter 模塊抽取,實際上就是通過打包命令生成這兩個產物,并將它們封裝成一個 pod 供iOS原生工程引用。
類似地,首先我們在 Flutter_library 的根目錄下,執行 iOS 打包構建命令。
Flutter build ios --debug這條命令的作用是編譯 Flutter 工程生成兩個產物:Flutter.framework 和 App.framework。同樣,把 debug 換成 release 就可以構建 release 產物(當然,你還需要處理一下簽名問題)。
然后,在 iOSDemo 的根目錄下創建一個名為 FlutterEngine 的目錄,并把這兩個 framework 文件拷貝進去。iOS 的模塊化產物工作要比 Android 多一個步驟,因為我們需要把這兩個產物手動封裝成 pod。因此,我們還需要在該目錄下創建 FlutterEngine.podspec,即 Flutter 模塊的組件定義。
Pod::Spec.new do |s|s.name = 'FlutterEngine's.version = '0.1.0's.summary = 'XXXXXXX's.description = <<-DESC TODO: Add long description of the pod here.DESCs.homepage = 'https://github.com/xx/FlutterEngine's.license = { :type => 'MIT', :file => 'LICENSE' }s.author = { 'chenhang' => 'hangisnice@gmail.com' }s.source = { :git => "", :tag => "#{s.version}" }s.ios.deployment_target = '8.0's.ios.vendored_frameworks = 'App.framework', 'Flutter.framework' end然后,執行pod lib lint 命令,Flutter 模塊組件就已經做好了。接下來,我們再修改 Podfile 文件把它集成到 iOSDemo 工程中,添加如下腳本。
... target 'iOSDemo' dopod 'FlutterEngine', :path => './' end然后,執行pod install 命令,Flutter 模塊就集成進 iOS 原生工程中了。再次,我們試著修改一下 AppDelegate.m 的代碼,把 window 的 rootViewController 改成 FlutterViewController,如下所示。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];FlutterViewController *vc = [[FlutterViewController alloc]init];[vc setInitialRoute:@"defaultRoute"]; //路由標識符self.window.rootViewController = vc;[self.window makeKeyAndVisible];return YES; }最后運行原生項目,一個寫著“Hello from Flutter”的全屏紅色的 Flutter Widget 也展示出來了,如下圖所示。
總結
在原生工程中集成Flutter是現階段最常見的方式。通過分離 Android、iOS 和 Flutter 三端工程,抽離 Flutter 庫和引擎及工程代碼為組件庫,以 Android 和 iOS 平臺最常見的 aar 和 pod 形式接入原生工程,從而將不同平臺的構建產物依照標準組件化的形式進行管理。
如果每次通過構建 Flutter 模塊工程,都是手動搬運 Flutter 編譯產物,那很容易就會因為工程管理混亂導致 Flutter 組件庫被覆蓋,從而引發難以排查的 Bug。而要解決此類問題的話,我們可以引入 CI 自動構建框架,把 Flutter 編譯產物構建自動化,原生工程通過接入不同版本的構建產物,實現更優雅的三端分離模式。
總結
以上是生活随笔為你收集整理的flutter打包的app有多大_Flutter原生混合开发的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: p30可以反向充电吗
- 下一篇: ps如何修旧的老照片(ps中如何羽化图片