Flutter混合開發(fā)項(xiàng)目搭建

官方提供的集成步驟詳見:
https://github.com/flutter/flutter/wiki/Add-Flutter-to-existing-apps
目前混合開發(fā)的集成方案還是preview版本,所以實(shí)際使用過程中,容易碰到各種問題锨匆,還不夠穩(wěn)定尼荆。
本文配置基于:
1.7.8-hotfix-4
官方文檔只能用于master分支,所以會有一些細(xì)節(jié)差異崩掘。

創(chuàng)建Flutter工程

假設(shè)當(dāng)前目錄結(jié)構(gòu)如下翼抠,ios和android工程在同一目錄下:

some/path/
  - android_project/
  - ios_project/

進(jìn)入some/path/目錄,創(chuàng)建Flutter module:

flutter create -t module --org com.example my_flutter

執(zhí)行完后扼鞋,目錄結(jié)構(gòu)如下:

some/path/
  - android_project/
  - ios_project/
  - my_flutter

my_flutter會生成隱藏的.android和.ios文件夾申鱼,注意盡量不要在這兩個隱藏文件夾里面添加自己的代碼,在pubspec.yaml更新時云头,這兩個文件夾會被重新覆蓋捐友,導(dǎo)致后來添加的文件丟失

配置Android工程

修改原生工程android_project下的app module中的build.gradle盘寡,在android{}配置中添加一下內(nèi)容

android {
  //...
  compileOptions {
    sourceCompatibility 1.8
    targetCompatibility 1.8
  }
}

依賴Flutter Module工程的方式有兩種:依賴aar與直接依賴源碼

依賴aar

$ cd some/path/my_flutter
$ flutter build aar

注意:build aar命令到1.7.8-hotfix-4還不支持楚殿,master分支已經(jīng)更新。
在flutter module工程竿痰,使用flutter build命令構(gòu)建出一個aar脆粥,然后android_project就去配置依賴這個aar,這樣做的優(yōu)點(diǎn)是android_project項(xiàng)目編譯的時候不需要去依賴Flutter SDK影涉,
直接引用aar即可变隔,缺點(diǎn)是開發(fā)的時候,沒法一鍵運(yùn)行蟹倾。

依賴源碼

依賴源碼匣缘,可以一鍵運(yùn)行,不過android_project項(xiàng)目編譯的時候需要去依賴Flutter SDK鲜棠。
android_project項(xiàng)目在setting.gradle添加以下代碼

include ':app'                                     // assumed existing content
setBinding(new Binding([gradle: this]))                                 // new
evaluate(new File(                                                      // new
  settingsDir.parentFile,                                               // new
  'my_flutter/.android/include_flutter.groovy'                          // new
))     

目錄結(jié)構(gòu)如下:


0bc3eb99-face-4ab8-af0b-de3f3a4028e3.png

Flutter工程以及在pubspec.yaml引用的library肌厨,就能作為一個project被引入,最后在build.gradle添加依賴Flutter工程:

dependencies {
  implementation project(':flutter')
}

調(diào)起Flutter界面

Android端

1豁陆、使用FlutterView

// MyApp/app/src/main/java/some/package/MainActivity.java
View flutterView = Flutter.createView(
        MainActivity.this,
        getLifecycle(),
        "route1"
);
FrameLayout.LayoutParams layout = new FrameLayout.LayoutParams(600, 800);
layout.leftMargin = 100;
layout.topMargin = 200;
addContentView(flutterView, layout);

2柑爸、使用FlutterFragment

// MyApp/app/src/main/java/some/package/MainActivity.java
FragmentTransaction tx = getSupportFragmentManager().beginTransaction();
tx.replace(R.id.someContainer, Flutter.createFragment("route1"));
tx.commit();

3、使用FlutterActivity

public class MainActivity extends FlutterActivity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    GeneratedPluginRegistrant.registerWith(this);
  }
}

FlutterActivity可以通過intent指定routeName

intent.putExtra("route", "initRoute");

Flutter端

import 'dart:ui';
import 'package:flutter/material.dart';

void main() => runApp(_widgetForRoute(window.defaultRouteName));

Widget _widgetForRoute(String route) {
  switch (route) {
    case 'route1':
      return SomeWidget(...);
    case 'route2':
      return SomeOtherWidget(...);
    default:
      return Center(
        child: Text('Unknown route: $route', textDirection: TextDirection.ltr),
      );
  }
}

創(chuàng)建FlutterView或者FlutterFragment時盒音,傳入了一個initialRoute表鳍,也就是window.defaultRouteName的值,這樣我們就能夠根據(jù)routeName來決定跳轉(zhuǎn)到哪個Flutter頁面祥诽。

配置ios工程

集成Flutter module工程到flutter_host_ios工程需要Cocoapods依賴項(xiàng)管理器譬圣,請確保本地安裝了cocoapods,如果未安裝雄坪,可以參考:cocoapods.org/
1厘熟、如果ios_project工程中已經(jīng)使用了cocoapods,將下列配置添加到工程的Podfile文件中:

flutter_application_path = 'path/to/my_flutter/'
load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')

2、找到項(xiàng)目TARGETS的Build Phases绳姨,點(diǎn)擊左上角+號選擇New Run Script Phase添加Run Script颇玷,在Shell字段下添加下面兩行腳本

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

這段跟官方文檔有差異,如果是master分支就缆,參考官方文檔。

2谒亦、執(zhí)行pod install
每次pubspec.yaml依賴有更新時竭宰,都需要重新執(zhí)行pod install

3、因?yàn)镕lutter現(xiàn)在不支持bitcode份招,需要禁用項(xiàng)目TARGETS的Build Settings-> Build Options-> Enable Bitcode部分中的ENABLE_BITCODE標(biāo)志切揭。

調(diào)起Flutter界面

在ios_project中,將AppDelegate改為繼承FlutterAppDelegate锁摔。
AppDelegate.h

#import <UIKit/UIKit.h>
#import <Flutter/Flutter.h>AppDelegate.m

@interface AppDelegate : FlutterAppDelegate
@property (nonatomic,strong) FlutterEngine *flutterEngine;
@end

AppDelegate.m

#import <FlutterPluginRegistrant/GeneratedPluginRegistrant.h> // Only if you have Flutter Plugins

#include "AppDelegate.h"

@implementation AppDelegate

// This override can be omitted if you do not have any Flutter Plugins.
- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  self.flutterEngine = [[FlutterEngine alloc] initWithName:@"io.flutter" project:nil];
  [self.flutterEngine runWithEntrypoint:nil];
  [GeneratedPluginRegistrant registerWithRegistry:self.flutterEngine];
  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

@end

ViewController.m

#import <Flutter/Flutter.h>
#import "AppDelegate.h"
#import "ViewController.h"

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
    [button addTarget:self
               action:@selector(handleButtonAction)
     forControlEvents:UIControlEventTouchUpInside];
    [button setTitle:@"Press me" forState:UIControlStateNormal];
    [button setBackgroundColor:[UIColor blueColor]];
    button.frame = CGRectMake(80.0, 210.0, 160.0, 40.0);
    [self.view addSubview:button];
}

- (void)handleButtonAction {
    FlutterEngine *flutterEngine = [(AppDelegate *)[[UIApplication sharedApplication] delegate] flutterEngine];
    FlutterViewController *flutterViewController = [[FlutterViewController alloc] initWithEngine:flutterEngine nibName:nil bundle:nil];
    [self presentViewController:flutterViewController animated:false completion:nil];
}
@end

與Android一樣廓旬,F(xiàn)lutterViewController也可以設(shè)置routeName

[flutterViewController setInitialRoute:@"route1"];

但是,這個api目前基本是無法派上用場谐腰,上述例子共用了FlutterEngine孕豹,在runWithEntrypoint執(zhí)行之后,main.dart中runApp代碼已經(jīng)執(zhí)行十气,后面再去setInitialRoute已經(jīng)沒有效果励背,F(xiàn)lutterViewController使用initWithNibName等其他方式初始化,不共用FlutterEngine砸西,main.dart還沒執(zhí)行叶眉,這種方式setInitialRoute能夠起作用,不過跳轉(zhuǎn)到Flutter頁面時芹枷,會展示launch頁面衅疙,體驗(yàn)不好。

熱重載

在宿主app進(jìn)程運(yùn)行以后鸳慈,進(jìn)入my_flutter,執(zhí)行:

$ cd some/path/my_flutter
$ flutter attach
Waiting for a connection from Flutter on Nexus 5X...

attach成功之后饱溢,就可以隨時修改flutter代碼,進(jìn)行熱重載更新蝶涩。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末理朋,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子绿聘,更是在濱河造成了極大的恐慌嗽上,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件熄攘,死亡現(xiàn)場離奇詭異兽愤,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進(jìn)店門浅萧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來逐沙,“玉大人,你說我怎么就攤上這事洼畅》园福” “怎么了?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵帝簇,是天一觀的道長徘郭。 經(jīng)常有香客問我,道長丧肴,這世上最難降的妖魔是什么残揉? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮芋浮,結(jié)果婚禮上抱环,老公的妹妹穿的比我還像新娘。我一直安慰自己纸巷,他們只是感情好镇草,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著瘤旨,像睡著了一般陶夜。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上裆站,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天条辟,我揣著相機(jī)與錄音,去河邊找鬼宏胯。 笑死羽嫡,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的肩袍。 我是一名探鬼主播杭棵,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼氛赐!你這毒婦竟也來了魂爪?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤艰管,失蹤者是張志新(化名)和其女友劉穎滓侍,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體牲芋,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡撩笆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年捺球,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片夕冲。...
    茶點(diǎn)故事閱讀 38,163評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡氮兵,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出歹鱼,到底是詐尸還是另有隱情泣栈,我是刑警寧澤,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布弥姻,位于F島的核電站秩霍,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏蚁阳。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一鸽照、第九天 我趴在偏房一處隱蔽的房頂上張望螺捐。 院中可真熱鬧,春花似錦矮燎、人聲如沸定血。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽澜沟。三九已至,卻和暖如春峡谊,著一層夾襖步出監(jiān)牢的瞬間茫虽,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工既们, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留濒析,地道東北人。 一個月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓啥纸,卻偏偏與公主長得像号杏,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子斯棒,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評論 2 344

推薦閱讀更多精彩內(nèi)容