<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Flutter 混合開發(fā)

          共 8792字,需瀏覽 18分鐘

           ·

          2021-01-28 13:28

          作者:xiangzhihong
          來源:SegmentFault 思否社區(qū)




          混合開發(fā)簡介


          使用 Flutter 從零開始開發(fā)App是一件輕松愜意的事情,但對于一些成熟的產(chǎn)品來說,完全摒棄原有 App 的歷史沉淀,全面轉(zhuǎn)向 Flutter 是不現(xiàn)實的。因此使用 Flutter 去統(tǒng)一 Android、iOS 技術棧,把它作為已有原生 App 的擴展能力,通過有序推進來提升移動終端的開發(fā)效率。


          目前,想要在已有的原生 App 里嵌入一些 Flutter 頁面主要有兩種方案。一種是將原生工程作為 Flutter 工程的子工程,由 Flutter 進行統(tǒng)一管理,這種模式稱為統(tǒng)一管理模式。另一種是將 Flutter 工程作為原生工程的子模塊,維持原有的原生工程管理方式不變,這種模式被稱為三端分離模式。




          在 Flutter 框架出現(xiàn)早期,由于官方提供的混編方式以及資料有限,國內(nèi)較早使用 Flutter 進行混合開發(fā)的團隊大多使用的是統(tǒng)一管理模式。但是,隨著業(yè)務迭代的深入,統(tǒng)一管理模式的弊端也隨之顯露,不僅三端(Android、iOS和Flutter)代碼耦合嚴重,相關工具鏈耗時也隨之大幅增長,最終導致開發(fā)效率降低。所以,后續(xù)使用 Flutter 進行混合開發(fā)的團隊大多使用三端代碼分離的模式來進行依賴治理,最終實現(xiàn) Flutter 工程的輕量級接入。


          除了可以輕量級接入外,三端代碼分離模式還可以把 Flutter 模塊作為原生工程的子模塊,從而快速地接入 Flutter 模塊,降低原生工程的改造成本。在完成對 Flutter 模塊的接入后,F(xiàn)lutter 工程可以使用 Android Studio 進行開發(fā),無需再打開原生工程就可以對 Dart 代碼和原生代碼進行開發(fā)調(diào)試。


          使用三端分離模式進行 Flutter 混合開發(fā)的關鍵是抽離 Flutter 工程,將不同平臺的構(gòu)建產(chǎn)物依照標準組件化的形式進行管理,即 Android 使用 aar、iOS 使用 pod。也就是說,F(xiàn)lutter 的混編方案其實就是將 Flutter 模塊打包成 aar 或者 pod 庫,然后在原生工程像引用其他第三方原生組件庫那樣引入 Flutter 模塊即可。




          Flutter 模塊


          默認情況下,新創(chuàng)建的 Flutter 工程會包含 Flutter 目錄和原生工程的目錄。在這種情況下,原生工程會依賴 Flutter 工程的庫和資源,并且無法脫離 Flutter 工程獨立構(gòu)建和運行。


          在混合開發(fā)中,原生工程對 Flutter 的依賴主要分為兩部分。一個是 Flutter 的庫和引擎,主要包含 Flutter 的 Framework 庫和引擎庫;另一個是 Flutter 模塊工程,即 Flutter 混合開發(fā)中的 Flutter 功能模塊,主要包括 Flutter 工程 lib 目錄下的 Dart 代碼實現(xiàn)。


          對于原生工程來說,集成 Flutter 只需要在同級目錄創(chuàng)建一個 Flutter 模塊,然后構(gòu)建 iOS 和 Android 各自的 Flutter 依賴庫即可。接下來,我們只需要在原生項目的同級目錄下,執(zhí)行 Flutter 提供的構(gòu)建模塊命令創(chuàng)建 Flutter 模塊即可,如下所示。


          flutter?create?-t?module?flutter_library


          其中,flutter_library 為 Flutter 模塊名。執(zhí)行上面的命令后,會在原生工程的同級目錄下生成一個 flutter_library 模塊工程。Flutter 模塊也是 Flutter 工程,使用 Android Studio 打開它,其目錄如下圖所示。



          可以看到,和普通的 Flutter 工程相比,F(xiàn)lutter 模塊工程也內(nèi)嵌了 Android 工程和 iOS 工程,只不過默認情況下,Android 工程和 iOS 工程是隱藏的。因此,對于 Flutter 模塊工程來說,也可以像普通工程一樣使用 Android Studio 進行開發(fā)和調(diào)試。


          同時,相比普通的 Flutter 工程,F(xiàn)lutter 模塊工程的 Android 工程目錄下多了一個 Flutter 目錄,此目錄下的 build.gradle 配置就是我們構(gòu)建 aar 時的打包配置。同樣,在 Flutter 模塊工程的 iOS 工程目錄下也會找到一個 Flutter 目錄,這也是 Flutter 模塊工程既能像 Flutter 普通工程一樣使用 Android Studio 進行開發(fā)調(diào)試,又能打包構(gòu)建 aar 或 pod 的原因。




          Android 集成 Flutter


          在原生 Android 工程中集成 Flutter,原生工程對 Flutter 的依賴主要包括兩部分,分別是 Flutter 庫和引擎,以及 Flutter 工程構(gòu)建產(chǎn)物。


          • Flutter 庫和引擎:包含 icudtl.dat、libFlutter.so 以及一些 class 文件,最終這些文件都會被封裝到 Flutter.jar 中。
          • Flutter 工程產(chǎn)物:包括應用程序數(shù)據(jù)段 isolate_snapshot_data、應用程序指令段 isolate_snapshot_instr、虛擬機數(shù)據(jù)段 vm_snapshot_data、虛擬機指令段 vm_snapshot_instr 以及資源文件 flutter_assets。

          和原生 Android 工程集成其他插件庫的方式一樣,在原生 Android 工程中引入 Flutter 模塊需要先在 settings.gradle 中添加如下代碼。

          setBinding(new?Binding([gradle:?this]))
          evaluate(new?File(
          ??settingsDir.parentFile,
          ??'flutter_library/.android/include_flutter.groovy'))

          其中,flutter_library 為我們創(chuàng)建的 Flutter 模塊。然后,在原生 Android 工程的 app 目錄的 build.gradle 文件中添加如下依賴。

          dependencies?{
          ????implementation?project(":flutter")
          }

          然后編譯并運行原生 Android 工程,如果沒有任何錯誤則說明集成 Flutter 模塊成功。需要說明的是,由于Flutter 支持的最低版本為16,所以需要將 Android 項目的 minSdkVersion 修改為16。

          如果出現(xiàn)“程序包 android.support.annotation 不存在”的錯誤,需要使用如下的命令來創(chuàng)建 Flutter 模塊,因為最新版本的 Android 默認使用 androidx 來管理包。

          flutter?create?--androidx?-t?module?flutter_library

          對于 Android 原生工程,如果還沒有升級到 androidx,可以在原生 Android 工程上右鍵,然后依次選擇【Refactor】→【Migrate to Androidx】將 Android 工程升級到 androidx 包管理。

          在原生 Android 工程中成功添加 Flutter 模塊依賴后,打開原生 Android 工程,并在應用的入口 MainActivity 文件中添加如下代碼。

          public?class?MainActivity?extends?AppCompatActivity?{

          ????@Override
          ????protected?void?onCreate(Bundle?savedInstanceState)?{
          ????????super.onCreate(savedInstanceState);
          ????????View?flutterView?=?Flutter.createView(this,?getLifecycle(),?"route1");
          ????????FrameLayout.LayoutParams?layoutParams?=?new?FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,?ViewGroup.LayoutParams.MATCH_PARENT);
          ????????addContentView(flutterView,?layoutParams);
          ????}
          }

          通過 Flutter 提供的 createView() 方法,可以將 Flutter 頁面構(gòu)建成 Android 能夠識別的視圖,然后將這個視圖使用 Android 提供的 addContentView() 方法添加到父窗口即可。重新運行原生 Android 工程,最終效果如下圖所示。



          如果原生 Android 的 MainActivity 加載的是一個 FrameLayout,那么加載只需要將 Flutter 頁面構(gòu)建成一個 Fragment 即可,如下所示。

          public?class?MainActivity?extends?AppCompatActivity?{

          ????@Override
          ????protected?void?onCreate(Bundle?savedInstanceState)?{
          ????????super.onCreate(savedInstanceState);
          ????????setContentView(R.layout.activity_main);
          ????????FragmentTransaction?ft=?getSupportFragmentManager().beginTransaction();
          ????????ft.replace(R.id.fragment_container,?Flutter.createFragment("Hello?Flutter"));
          ????????ft.commit();
          ????}
          }

          除了使用 Flutter 模塊方式集成外,還可以將 Flutter 模塊打包成 aar,然后再添加依賴。在 flutter_library 根目錄下執(zhí)行 aar 打包構(gòu)建命令即可抽取 Flutter 依賴,如下所示。

          flutter?build?apk?--debug

          此命令的作用是將 Flutter 庫和引擎以及工程產(chǎn)物編譯成一個 aar 包,上面命令編譯的 aar 包是 debug 版本,如果需要構(gòu)建 release 版本,只需要把命令中的 debug 換成 release 即可。

          打包構(gòu)建的 flutter-debug.aar 位于 .android/Flutter/build/outputs/aar/ 目錄下,可以把它拷貝到原生 Android 工程的 app/libs 目錄下,然后在原生 Android 工程的 app 目錄的打包配置 build.gradle 中添加對它的依賴,如下所示。

          dependencies?{
          ??implementation(name:?'flutter-debug',?ext:?'aar')???
          }

          然后重新編譯一下項目,如果沒有任何錯誤提示則說明 Flutter 模塊被成功集成到 Android 原生工程中。



          iOS 集成 Flutter


          原生 iOS 工程對 Flutter 的依賴包含 Flutter 庫和引擎,以及 Flutter 工程編譯產(chǎn)物。其中,F(xiàn)lutter 庫和引擎指的是 Flutter.framework 等,F(xiàn)lutter 工程編譯產(chǎn)物指的是 App.framework 等。

          在原生 iOS 工程中集成 Flutter 需要先配置好 CocoaPods,CocoaPods 是 iOS 的類庫管理工具,用來管理第三方開源庫。在原生 iOS 工程中執(zhí)行 pod init 命令創(chuàng)建一個 Podfile 文件,然后在 Podfile 文件中添加 Flutter 模塊依賴,如下所示。

          flutter_application_path?=?'../flutter_?library/
          load?File.join(flutter_application_path,?'
          .ios',?'Flutter',?'podhelper.rb')

          target?'
          iOSDemo'?do
          ??#?Comment?the?next?line?if?you?don'
          t?want?to?use?dynamic?frameworks
          ??use_frameworks!
          ??install_all_flutter_pods(flutter_application_path)

          ??#?Pods?for?iOSDemo
          ??…?//省略其他腳本
          end?'

          然后,關閉原生 iOS 工程,并在原生 iOS 工程的根目錄執(zhí)行 pod install 命令安裝所需的依賴包。安裝完成后,使用 Xcode 打開 iOSDemo.xcworkspace 原生工程。

          默認情況下,F(xiàn)lutter 是不支持 Bitcode 的,Bitcode 是一種 iOS 編譯程序的中間代碼,在原生 iOS 工程中集成 Flutter 需要禁用 Bitcode。在 Xcode 中依次選擇【TAGETS】→【Build Setttings】→【Build Options】→【Enable Bitcode】來禁用 Bitcode,如下圖所示。



          如果使用的是 Flutter 早期的版本,還需要添加 build phase 來支持構(gòu)建 Dart 代碼。依次選擇【TAGGETS】→【Build Settings】→【Enable Phases】,然后點擊左上角的加號新建一個“New Run Script Phase”,添加如下腳本代碼。

          "$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh"?build
          "$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh"?embed

          不過,最新版本的Flutter已經(jīng)不需要再添加腳本了。重新運行原生iOS工程,如果沒有任何錯誤則說明iOS成功集成Flutter模塊。

          除了使用Flutter模塊方式外,還可以將Flutter模塊打包成可以依賴的動態(tài)庫,然后再使用CocoaPods添加動態(tài)庫。首先,在flutter_library根目錄下執(zhí)行打包構(gòu)建命令生成framework動態(tài)庫,如下所示。

          flutter?build?ios?--debug

          上面命令是將 Flutter 工程編譯成 Flutter.framework 和 App.framework 動態(tài)庫。如果要生成 release 版本,只需要把命令中的 debug 換成 release 即可。

          然后,在原生 iOS 工程的根目錄下創(chuàng)建一個名為 FlutterEngine 的目錄,并把生成的兩個framework 動態(tài)庫文件拷貝進去。不過,iOS 生成模塊化產(chǎn)物要比 Android 多一個步驟,因為需要把 Flutter 工程編譯生成的庫手動封裝成一個 pod。首先,在 flutter_ library 該目錄下創(chuàng)建 FlutterEngine.podspec,然后添加如下腳本代碼。

          Pod::Spec.new?do?|s|
          ??s.name?????????????=?'FlutterEngine'
          ??s.version??????????=?'0.1.0'
          ??s.summary??????????=?'FlutterEngine'
          ??s.description??????=?<<-DESC
          TODO:?Add?long?description?of?the?pod?here.
          ???????????????????????DESC
          ??s.homepage?????????=?'https://github.com/xx/FlutterEngine'
          ??s.license??????????=?{?:type?=>?'MIT',?:file?=>?'LICENSE'?}
          ??s.author???????????=?{?'xzh'?=>?'[email protected]'?}
          ??s.source???????=?{?:git?=>?"",?:tag?=>?"#{s.version}"?}
          ??s.ios.deployment_target?=?'9.0'
          ??s.ios.vendored_frameworks?=?'App.framework',?'Flutter.framework'
          end

          然后,執(zhí)行 pod lib lint 命令即可拉取 Flutter 模塊所需的組件。接下來,在原生 iOS 工程的 Podfile 文件添加生成的庫即可。

          target?'iOSDemo'?do
          ????pod?'FlutterEngine',?:path?=>?'./'
          end

          重新執(zhí)行 pod install 命令安裝依賴庫,原生 iOS 工程集成 Flutter 模塊就完成了。接下來,使用 Xcode 打開 ViewController.m 文件,然后添加如下代碼。

          #import?"ViewController.h"
          #import?
          #import?

          @interface?ViewController?()

          @end

          @implementation?ViewController

          -?(void)viewDidLoad?{
          ????[super?viewDidLoad];
          ????UIButton?*button?=?[[UIButton?alloc]init];
          ????[button?setTitle:@"加載Flutter模塊"?forState:UIControlStateNormal];
          ????button.backgroundColor=[UIColor?redColor];
          ????button.frame?=?CGRectMake(50,?50,?200,?100);
          ????[button?setTitleColor:[UIColor?redColor]?forState:UIControlStateHighlighted];
          ????[button?addTarget:self?action:@selector(buttonPrint)?forControlEvents:UIControlEventTouchUpInside];
          ????[self.view?addSubview:button];
          }

          -?(void)buttonPrint{
          ????FlutterViewController?*?flutterVC?=?[[FlutterViewController?alloc]init];
          ????[flutterVC?setInitialRoute:@"defaultRoute"];
          ????[self?presentViewController:flutterVC?animated:true?completion:nil];
          }

          @end

          在上面的代碼中,我們在原生 iOS 中創(chuàng)建了一個按鈕,點擊按鈕時就會跳轉(zhuǎn)到 Flutter 頁面,最終效果如下圖所示。



          默認情況下,F(xiàn)lutter 為提供了兩種調(diào)用方式,分別是 FlutterViewController 和FlutterEngine。對于 FlutterViewController 來說,打開 ViewController.m 文件,在里面添加一個加載 flutter 頁面的方法并且添加一個按鈕看來調(diào)用。



          Flutter 模塊調(diào)試


          眾所周知,F(xiàn)lutter 的優(yōu)勢之一就是在開發(fā)過程中使用熱重載功能來實現(xiàn)快速調(diào)試。默認情況下,在原生工程中集成 Flutter 模塊后熱重載功能是失效的,需要重新運行原生工程才能看到效果。如此一來,F(xiàn)lutter 開發(fā)的熱重載優(yōu)勢就失去了,并且開發(fā)效率也隨之降低。

          那么,能不能在混合項目中開啟 Flutter 的熱重載呢?答案是可以的,只需要經(jīng)過如下步驟即可開啟熱重載功能。首先,關閉原生應用,此處所說的關閉是指關閉應用的進程,而不是簡單的退出應用。在 Flutter 模塊的根目錄中輸入 flutter attach 命令,然后再次打開原生應用,就會看到連接成功的提示,如下圖所示。



          如果同時連接了多臺設備,可以使用 flutter attach -d 命令來指定連接的設備。接下來,只需要按r鍵即可執(zhí)行熱重載,按R鍵即可執(zhí)行熱重啟,按d鍵即可斷開連接。

          在 Flutter 工程中,我們可以直接點擊debug按鈕來進行代碼調(diào)試,但在混合項目中,直接點擊 debug 按鈕是不起作用的。此時,可以使用 Android Studio 提供的 flutter attach 按鈕來建立與 flutter 模塊的連接,進行實現(xiàn)對 flutter 模塊的代碼調(diào)試,如圖下圖所示。



          上面只是完成了在原生工程中引入 Flutter 模塊,具體開發(fā)時還會遇到與 Flutter 模塊的通信問題、路由管理問題,以及打包等。



          點擊左下角閱讀原文,到?SegmentFault 思否社區(qū)?和文章作者展開更多互動和交流,或掃描下方二維碼添加“?SF 思否小姐姐?”,回復“?入群?”即可加入我們的技術交流群,收獲更多的技術文章~

          -?END -

          瀏覽 48
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  青青草成人免费观看 | 国产热99| 99视频在线免费观看视频 | 午夜神马久久 | 国产A片视频 |