<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ā)

          共 7806字,需瀏覽 16分鐘

           ·

          2020-11-05 12:23

          來源 |?https://segmentfault.com/a/1190000021634067

          混合開發(fā)簡介

          使用Flutter從零開始開發(fā)App是一件輕松愜意的事情,但對于某些成熟的產(chǎn)品而言,完全替代棄用App的歷史沉淀,全面轉(zhuǎn)向Flutter是不現(xiàn)實(shí)的。
          因此使用Flutter去統(tǒng)一Android,iOS技術(shù)棧,把它作為現(xiàn)有原生App的擴(kuò)展能力,通過有序推進(jìn)來提升移動終端的開發(fā)效率。
          結(jié)果,想要在已有的原生App里嵌入一些Flutter頁面主要有兩種方案。一種是將另一種是將Flutter工程作為原生工程的子模塊,維持固有的原生工程管理方式不變,這是原生的作為Flutter工程的子工程,由Flutter進(jìn)行統(tǒng)一管理,這種模式稱為統(tǒng)一管理模式。這種模式被稱為三端分離模式。

          在Flutter框架出現(xiàn)早期,由于官方提供的混編方式以及資料有限,國內(nèi)較早使用Flutter進(jìn)行混合開發(fā)的團(tuán)隊(duì)大多使用的是統(tǒng)一管理模式。
          但是,通過業(yè)務(wù)轉(zhuǎn)換的深度,統(tǒng)一管理模式的弊端也也隨之顯露,幾乎三端(Android,iOS和Flutter)代碼替換嚴(yán)重,相關(guān)工具鏈耗時也隨之增長,最終導(dǎo)致開發(fā)效率降低。
          所以,后續(xù)使用Flutter進(jìn)行混合開發(fā)的團(tuán)隊(duì)大多使用三端代碼分離的模式來進(jìn)行依賴治理,最終實(shí)現(xiàn)顫振工程的輕量級接入。
          除了可以輕量級接入外,三端代碼分離模式還可以把顫振模塊作為原生工程的子模塊,從而快速地接入在完成對Flutter模塊的接收后,F(xiàn)lutter工程可以使用Android Studio進(jìn)行開發(fā),無需再打開原生工程就可以對Dart代碼和原生代碼進(jìn)行開發(fā)調(diào)試。
          使用三端分離模式進(jìn)行Flutter混合開發(fā)的關(guān)鍵是抽離Flutter工程,將不同平臺的生成標(biāo)準(zhǔn)框架化的形式進(jìn)行管理,即Android使用aar,iOS使用pod。
          這樣,F(xiàn)lutter的混編方案實(shí)際上就是將Flutter模塊打包成aar或者pod庫,然后在原生工程像引用其他第三方原生組件庫那樣?Flutter模塊即可。

          顫振模塊

          在這種情況下,原生工程會依賴Flutter工程的庫和資源,并且無法分開Flutter工程獨(dú)立建造和運(yùn)行。
          在混合開發(fā)中,是原生的對Flutter的依賴主要分為兩部分。
          一個是Flutter的庫和引擎,主要包含F(xiàn)lutter的框架庫和引擎庫;另一個是Flutter模塊工程,即Flutter混合開發(fā)中的Flutter功能模塊,主要包括撲工程的lib目錄下的飛鏢代碼實(shí)現(xiàn)。
          對于原生工程來說,集成撲只需要在同級目錄創(chuàng)建一個撲模塊,然后構(gòu)建的iOS和安卓各自的撲依賴庫即可。
          接下來,我們只需要在原生項(xiàng)目的同級目錄下,執(zhí)行Flutter提供的內(nèi)置模塊命令創(chuàng)建Flutter模塊即可,如下所示。
          flutter create -t module flutter_library
          執(zhí)行上面的命令后,會在原始工程的同級目錄下生成一個flutter_library模塊工程。Flutter模塊也是Flutter工程,使用Android Studio打開它,其目錄如下圖所示。


          可以看到,和普通的Flutter工程比例,F(xiàn)lutter模塊工程也內(nèi)嵌了Android工程和iOS工程,只不過偶爾情況下,Android工程和iOS工程是隱藏的。因此,對于Flutter模塊工程而言,也可以像普通工程一樣使用Android Studio進(jìn)行開發(fā)和調(diào)試。
          同時,引用普通的Flutter工程,F(xiàn)lutter模塊工程的Android工程目錄下多了一個Flutter目錄,此目錄下的build.gradle配置就是我們建造aar時的打包配置。
          同樣,在Flutter模塊工程的iOS工程目錄下也會找到一個Flutter目錄,這也是Flutter模塊工程既能像Flutter普通工程一樣使用Android Studio進(jìn)行開發(fā)調(diào)試,又能打包構(gòu)建aar或pod的原因。

          Android集成Flutter

          在原生Android工程中集成的Flutter,原生工程對Flutter的依賴主要包括兩部分,分別是Flutter庫和引擎,以及Flutter工程生成的。
          • Flutter庫和引擎:包含icudtl.dat,libFlutter.so以及一些類文件,最終這些文件都會被封裝到Flutter.jar中。
          • Flutter工程材料:包括應(yīng)用程序數(shù)據(jù)段isolate_snapshot_data,應(yīng)用程序指令段isolate_snapshot_instr,虛擬機(jī)數(shù)據(jù)段vm_snapshot_data,虛擬機(jī)指令段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'))
          然后,在原生Android工程的app目錄的build.gradle文件中添加如下依賴。。,其中,flutter_library為我們創(chuàng)建的Flutter模塊。
          dependencies { implementation project(":flutter")}
          然后編譯并運(yùn)行原生Android工程,如果沒有任何錯誤則說明集成的Flutter模塊成功。需要說明的是,由于Flutter支持的最低版本為16,所以需要將Android項(xiàng)目的minSdkVersion修改為16。
          如果出現(xiàn)“程序包android .support.annotation不存在”的錯誤,需要使用如下的命令來創(chuàng)建Flutter模塊,因?yàn)樽钚掳姹镜腁ndroid或使用androidx來管理包。
          flutter create --androidx -t module flutter_library
          對于Android原生工程,如果還沒有升級到androidx,可以在原生Android工程上快捷鍵,然后依次選擇【重構(gòu)】→【遷移到Androidx】將Android工程升級到androidx包管理。
          在原生Android工程中成功添加Flutter模塊依賴后,打開原生Android工程,并在應(yīng)用的入口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頁面合并成Android能夠識別的視圖,然后將這個視圖使用Android提供的addContentView()方法添加到父窗口即可。重新運(yùn)行原生Android工程,最終效果如下圖可見。


          如果原生Android的MainActivity加載的是一個FrameLayout,那么加載只需放在Flutter頁面上構(gòu)建成一個片段即可,如下所示。
          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打包生成命令即可撤回Flutter依賴,如下所示。
          flutter build apk --debug
          此命令的作用是將Flutter庫和引擎以及工程生成編譯成一個aar包,上面命令編譯的aar包是debug版本,如果需要合并發(fā)行版本,只需要把命令中的debug換成release即可。
          打包編譯的Flutter-debug.aar位于.android / Flutter / build / outputs / aar /目錄下,可以把它復(fù)制到原生Android工程的app / libs目錄下,然后在原生Android工程的app目錄的打包配置build.gradle中添加對它的依賴,如下所示。
          dependencies { implementation(name: 'flutter-debug', ext: 'aar') }
          然后重新編譯一下項(xiàng)目,如果沒有任何錯誤提示則說明Flutter模塊被成功集成到Android原生工程中。

          iOS集成Flutter

          原生的iOS工程對顫振的依賴包含撲庫和引擎,以及撲工程編譯產(chǎn)物。其中,撲庫和引擎指的是Flutter.framework等,撲工程編譯產(chǎn)物指的是App.framework等。
          在原生的iOS工程中集成的Flutter需要先配置好CocoaPods,CocoaPods是iOS的類庫管理工具,用于管理第三方開源庫。可見。
          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 '
          然后,關(guān)閉原生iOS工程,并在原生iOS工程的根目錄執(zhí)行pod install命令安裝所需的依賴包。
          安裝完成后,使用Xcode打開iOSDemo.xcworkspace原生工程。有時情況下,F(xiàn)lutter是不支持Bitcode的,在Xcode中依次選擇【TAGETS】→【Build Settings】→【Build Options】→【Enable Bitcode】來替換Bitcode,如下所示。圖所示。


          如果選擇使用的是Flutter早期版本,還需要添加構(gòu)建階段來支持構(gòu)建Dart代碼。依次選擇【標(biāo)簽】→【構(gòu)建設(shè)置】→【啟用階段】,然后單擊左上角的加號新建一個“ 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)不需要再添加腳本了。重新運(yùn)行原生iOS工程,如果沒有任何錯誤則說明iOS成功集成了Flutter模塊。
          除了使用Flutter模塊方式外,還可以將Flutter模塊打包成可以依賴的動態(tài)庫,然后再使用CocoaPods添加動態(tài)庫。
          首先,在flutter_library根目錄下執(zhí)行打包生成命令生成框架動態(tài)庫,如下所示。
          flutter build ios --debug
          如果要生成發(fā)布版本,只需要把命令中的調(diào)試轉(zhuǎn)換成發(fā)布即可。
          然后,在原生iOS工程的根目錄下創(chuàng)建一個名為,F(xiàn)letchEngine的目錄,并把生成的兩個框架動態(tài)庫文件復(fù)制進(jìn)去。
          不過,iOS生成的紋理要比Android多一個步驟,因?yàn)樾枰袴lutter工程編譯生成的庫手動封裝成一個pod。首先,在flutter_庫該目錄下創(chuàng)建的FlutterEngine.podspec,然后添加如下腳本代碼。
          Pod::Spec.new do |s| s.name = 'FlutterEngine' s.version = '0.1.0' s.summary = 'FlutterEngine' s.description = <<-DESCTODO: 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)建了一個按鈕,點(diǎn)擊按鈕時就會變成到Flutter頁面,最終效果如下圖所示。


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

          Flutter模塊調(diào)試

          根本上,F(xiàn)lutter的優(yōu)勢之一就是在開發(fā)過程中使用熱重載功能來實(shí)現(xiàn)快速調(diào)試。替代情況下,在原生工程中集成的Flutter模塊后熱重載功能是無效的,需要重新運(yùn)行原生工程才能看到效果。
          如此一來,F(xiàn)lutter開發(fā)的熱重載優(yōu)勢就失去了,并且開發(fā)效率也隨之降低。
          那么,能不能在混合項(xiàng)目中開啟Flutter的熱重載呢?答案是可以的,只需要經(jīng)過如下首先,關(guān)閉原生應(yīng)用,此處所說的關(guān)閉是指關(guān)閉應(yīng)用的進(jìn)程,而不是簡單的退出應(yīng)用。
          在Flutter模塊的根目錄中輸入flutter attach命令,然后再次打開原生應(yīng)用,就會看到連接成功的提示,如下圖所示。

          如果,同時連接了多臺設(shè)備,可以使用Flutter attach -d命令來指定連接的設(shè)備。接下來,只需要按r鍵即可執(zhí)行熱重載,按R鍵即可執(zhí)行熱重啟,按d鍵即可斷開連接。
          在撲工程中,我們可以直接點(diǎn)擊調(diào)試按鈕來進(jìn)行代碼調(diào)試,但在混合項(xiàng)目中,直接點(diǎn)擊調(diào)試按鈕是不起作用的。
          此時,可以使用Android Studio中提供的附加撲按鈕來建立與flutter模塊的連接,進(jìn)行實(shí)現(xiàn)對flutter模塊的代碼調(diào)試,如圖下圖所示。


          上面只是完成了在原生工程中的Flutter模塊,具體開發(fā)時就要遇到與Flutter模塊的通信問題,路由管理問題,以及打包等。
          本文完~
          瀏覽 41
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <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>
                  亚洲精品黄色 | 伊人大香蕉伊人在线 | 四虎在线视频 | 九哥操逼王 | 欧美亚洲日韩一区二区三区 |