原生Android集成Flutter混合開發(fā)

原生Android和Flutter集成主要有兩種方案:

1.源碼集成:官方提供的源碼集成方案

2.產(chǎn)物集成:Flutter 項(xiàng)目單獨(dú)開發(fā)浓体,開發(fā)完成后發(fā)布成 aar 包或者 iOS 的 framework 形式泡挺,原生項(xiàng)目依賴 Flutter 輸出的文件即可。

3.咸魚團(tuán)隊(duì)的FlutterBoost 方案命浴。FlutterBoost地址

環(huán)境

首先確認(rèn)環(huán)境是否正確:
這里重點(diǎn)關(guān)注一下Flutter version的版本娄猫。在后面介紹集成開發(fā)的時(shí)候,不同的Flutter版本有差別生闲。

flutter doctor -v

下面是我的環(huán)境信息:


在這里插入圖片描述

集成

創(chuàng)建Android項(xiàng)目

略過新建 Native Android項(xiàng)目的流程媳溺。

注意點(diǎn):
(1)現(xiàn)在創(chuàng)建的Flutter module默認(rèn)是支持Android X的,所以如果想在現(xiàn)有的項(xiàng)目中集成Flutter module需要把support包替換成Android x碍讯。所有這里是通過新建一個(gè) Native Android項(xiàng)目(默認(rèn)支持Android x)來演示混合開發(fā)流程悬蔽。
(2)配置信息,需要在app/build.gradle里設(shè)置

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

創(chuàng)建Flutter module

  1. 切換 flutter 的 channel 到 master (master 分支下是 flutter 的 preview 版本)
flutter channel master
  1. 創(chuàng)建 flutter module項(xiàng)目
    module后面是新建的Flutter module的名稱冲茸。
flutter create -t module flutter_test
  1. Flutter module的目錄結(jié)構(gòu):

(1)在 flutter 的模塊項(xiàng)目中包含有一個(gè)隱藏的 .android 和 .ios 目錄這個(gè)目錄下是可運(yùn)行的 Android 和 iOS 項(xiàng)目屯阀。

(2)flutter代碼寫在 lib下,注意在 .android 和 .ios 目錄下都有一個(gè) Flutter 目錄轴术,這個(gè)是我們 flutter 的庫項(xiàng)目了难衰。也就是Android 用來生成 aar,iOS 用來生產(chǎn) framework 的庫逗栽。

(3 Flutter Application項(xiàng)目是沒有.android 和.ios目錄的盖袭。Flutter Application項(xiàng)目下對(duì)應(yīng)的是android和ios這兩個(gè)目錄。

在這里插入圖片描述
  1. git管理Flutter module

(1)把項(xiàng)目使用 git 管理起來,后面會(huì)在 native 項(xiàng)目中以submodule的形式引入native項(xiàng)目鳄虱。
略過git上傳到遠(yuǎn)程git倉庫的過程弟塞。

(2)重點(diǎn)關(guān)注一下gitignore文件的編輯

編輯一下項(xiàng)目下的 .gitignore 文件,需要把項(xiàng)目下的 .ios 和 .android 忽略掉拙已。
這里有個(gè)坑决记,有的文章說要把.packages也忽略掉,但是根據(jù)我的實(shí)驗(yàn)是不行的倍踪,建議大家還是把.packages通過git管理起來系宫。

(3)我的gitignore配置信息

.DS_Store
.dart_tool/
.pub/
.idea/
.vagrant/
.sconsign.dblite
.svn/
*.swp
profile
DerivedData/
.generated/
*.pbxuser
*.mode1v3
*.mode2v3
*.perspectivev3
!default.pbxuser
!default.mode1v3
!default.mode2v3
!default.perspectivev3
xcuserdata
*.moved-aside
*.pyc
*sync/
Icon?
.tags*
build/
.ios/Flutter/Generated.xconfig
.flutter-plugins

Native Android 項(xiàng)目集成 Flutter

  1. native android 項(xiàng)目集成 Flutter

(1)將目錄切換到native android代碼目錄下

(2)將Flutter module添加到native android中。

git submodule add flutter module的倉庫地址
git submodule update
  1. 在native android根目錄的 settings.gradle中添加如下配置
    這里的路徑使用的是相對(duì)于native android 項(xiàng)目的路徑建车。
setBinding(new Binding([gradle: this]))
evaluate(new File(
        settingsDir,
        'flutter_test/.android/include_flutter.groovy'
))
  1. 在native android項(xiàng)目的 app 目錄下的 build.gradle 文件中添加 Flutter 庫的依賴
implementation project(':flutter')
  1. 從新rebuild項(xiàng)目以后扩借,在native android項(xiàng)目目錄下會(huì)多一個(gè)flutter module子項(xiàng)目。

代碼編寫

通過native怎么加載flutter widget呢缤至?Flutter提供了以下集中方法潮罪。(Flutter不同版本存在差異)

6.1 通過FlutterFragment類
直接在對(duì)應(yīng)的native activity 布局文件中添加FlutterFragment即可。

 <fragment
            android:id="@+id/flutterfragment"
            android:name="io.flutter.embedding.android.FlutterFragment"
            android:layout_width="300dp"
            android:layout_height="500dp" />

6.2 通過FlutterActivity類
在 AndroidManifest.xml 中注冊(cè)

<activity
                android:name="io.flutter.embedding.android.FlutterActivity"
                android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
                android:exported="true"
                android:hardwareAccelerated="true"
                android:windowSoftInputMode="adjustResize" />

默認(rèn)啟動(dòng)方式:默認(rèn)路由為 '/'

import io.flutter.embedding.android.FlutterActivity
val intent = FlutterActivity.createDefaultIntent(this)
startActivity(intent)

啟動(dòng)到指定路由

 val customFlutter = FlutterActivity.withNewEngine()
            .initialRoute("newRoute")
            .build(this)
        startActivity(customFlutter)

6.3 通過FlutterView類
通過該類沒有實(shí)現(xiàn)效果领斥,待研究

 FlutterView flutterView = new FlutterView(this);
        FrameLayout frameLayout = findViewById(R.id.framelayout);
        frameLayout.addView(flutterView);
       //創(chuàng)建一個(gè) FlutterView 就可以了嫉到,這個(gè)時(shí)候還不會(huì)渲染。
      //調(diào)用下面代碼后才會(huì)渲染
        flutterView.attachToFlutterEngine(new FlutterEngine(this));

集成中經(jīng)歷的坑

  1. finished with non-zero exit value 1
Process 'command '/Users/mtdp/Documents/Flutter/flutter/bin/flutter'' finished with non-zero exit value 1

造成這個(gè)的原因是缺少.packages文件月洛,所有在通過git管理flutter module的時(shí)候屯碴,盡量把.packages保留。

  1. 廢棄類
    Flutter默認(rèn)在某個(gè)版本以后已經(jīng)不支持facade了膊存。
    Flutter version 1.7.8+hotfix.4版本還是支持的,具體從那個(gè)版本移除了忱叭,還不清楚隔崎。
io.flutter.facade.*

ps:以前的方式(deprecated) ( io.flutter.facade )
通過使用 Flutter.createView:

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

通過使用 Flutter.createFragment:

 FragmentTransaction tx = getSupportFragmentManager().beginTransaction();
    tx.replace(R.id.someContainer, Flutter.createFragment("route1"));
    tx.commit();

git submodule刪除后重新添加問題

  1. 重新添加git 子模塊出現(xiàn)的問題:
A git directory for 'formRenderLib' is found locally with remote(s):
  origin   xxxxxx
If you want to reuse this local git directory instead of cloning again from
  xxxx
use the '--force' option. If the local git directory is not the correct repo
or you are unsure what this means choose another name with the '--name' option.

說明沒有刪除干凈之前的module

  1. 解決方法:

    2.1 在native android主項(xiàng)目目錄下,刪除指定模塊的文件

 git rm --cached module名稱 

2.2 打開主項(xiàng)目目錄下 .gitmodules 刪除和submodule相關(guān)的配置信息

2.3 打開主項(xiàng)目目錄下 .git/config 文件刪除和submodule相關(guān)的配置信息

2.4 刪除.git下的緩存模塊

rm -rf .git/modules/submodule名稱

2.5 添加子模塊

git submodule add submodule的git倉庫
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市韵丑,隨后出現(xiàn)的幾起案子爵卒,更是在濱河造成了極大的恐慌,老刑警劉巖撵彻,帶你破解...
    沈念sama閱讀 211,194評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件钓株,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡陌僵,警方通過查閱死者的電腦和手機(jī)轴合,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來碗短,“玉大人受葛,你說我怎么就攤上這事霍骄。” “怎么了肿男?”我有些...
    開封第一講書人閱讀 156,780評(píng)論 0 346
  • 文/不壞的土叔 我叫張陵幸逆,是天一觀的道長。 經(jīng)常有香客問我闰渔,道長席函,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,388評(píng)論 1 283
  • 正文 為了忘掉前任冈涧,我火速辦了婚禮茂附,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘炕舵。我一直安慰自己何之,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評(píng)論 5 384
  • 文/花漫 我一把揭開白布咽筋。 她就那樣靜靜地躺著溶推,像睡著了一般。 火紅的嫁衣襯著肌膚如雪奸攻。 梳的紋絲不亂的頭發(fā)上蒜危,一...
    開封第一講書人閱讀 49,764評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音睹耐,去河邊找鬼辐赞。 笑死,一個(gè)胖子當(dāng)著我的面吹牛硝训,可吹牛的內(nèi)容都是我干的响委。 我是一名探鬼主播,決...
    沈念sama閱讀 38,907評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼窖梁,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼赘风!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起纵刘,我...
    開封第一講書人閱讀 37,679評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤邀窃,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后假哎,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體瞬捕,經(jīng)...
    沈念sama閱讀 44,122評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評(píng)論 2 325
  • 正文 我和宋清朗相戀三年舵抹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了肪虎。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,605評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡掏父,死狀恐怖笋轨,靈堂內(nèi)的尸體忽然破棺而出秆剪,到底是詐尸還是另有隱情,我是刑警寧澤爵政,帶...
    沈念sama閱讀 34,270評(píng)論 4 329
  • 正文 年R本政府宣布仅讽,位于F島的核電站,受9級(jí)特大地震影響钾挟,放射性物質(zhì)發(fā)生泄漏洁灵。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評(píng)論 3 312
  • 文/蒙蒙 一掺出、第九天 我趴在偏房一處隱蔽的房頂上張望徽千。 院中可真熱鬧,春花似錦汤锨、人聲如沸双抽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽牍汹。三九已至,卻和暖如春柬泽,著一層夾襖步出監(jiān)牢的瞬間慎菲,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評(píng)論 1 265
  • 我被黑心中介騙來泰國打工锨并, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留露该,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,297評(píng)論 2 360
  • 正文 我出身青樓第煮,卻偏偏與公主長得像解幼,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子包警,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評(píng)論 2 348

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