Flutter混合項(xiàng)目搭建之Flutter_Boot的使用

一、概念

1隘击、Flutterr_Boot

這是一個(gè)由咸魚技術(shù)出品,幫助你在已有原生應(yīng)用的情況下研铆,搭建flutter混合開發(fā)環(huán)境的工具埋同。 它提供了標(biāo)準(zhǔn)的混合工程結(jié)構(gòu),同時(shí)支持混合棧(一套原生和flutter之前頁面通信和過渡的方案)的快速接入棵红。

https://github.com/alibaba-flutter/flutter-boot

2凶赁、Flutter_Boost

官網(wǎng)介紹:新一代Flutter-Native混合解決方案。 FlutterBoost是一個(gè)Flutter插件,它可以輕松地為現(xiàn)有原生應(yīng)用程序提供Flutter混合集成方案虱肄。FlutterBoost的理念是將Flutter像Webview那樣來使用致板。在現(xiàn)有應(yīng)用程序中同時(shí)管理Native頁面和Flutter頁面并非易事。 FlutterBoost幫你處理頁面的映射和跳轉(zhuǎn)咏窿,你只需關(guān)心頁面的名字和參數(shù)即可(通痴寤颍可以是URL)。

https://github.com/alibaba/flutter_boost

二集嵌、準(zhǔn)備工作

npm安裝以及環(huán)境配置
flutter 的v1.9.1-hotfixes分支安裝以及環(huán)境配置萝挤,對(duì)應(yīng)flutter_boost版本是0.1.60---0.1.64
JDK,Android SDK 等環(huán)境配置正確

三根欧、開始混合項(xiàng)目搭建

項(xiàng)目地址:https://github.com/jingzhanwu/FlutterHybrid-FlutterBoot
1怜珍、安裝flutter_boot,命令行執(zhí)行:npm install flutter_boot

npm install flutter_boot
2咽块、初始化flutter_boot項(xiàng)目绘面,進(jìn)入要存放工程的目錄執(zhí)行:

flutter-boot init
接著會(huì)提示你輸入工程名稱


image.png

輸完工程名會(huì)一次提示你輸入flutter 倉庫地址、是否有android項(xiàng)目侈沪,是否有IOS項(xiàng)目揭璃、關(guān)聯(lián)本地項(xiàng)目等,根據(jù)自己項(xiàng)目需求選擇即可亭罪,如果你已經(jīng)有了android原生項(xiàng)目瘦馍,則最好在關(guān)聯(lián)android項(xiàng)目哪一步輸入本地native項(xiàng)目的路勁進(jìn)行關(guān)聯(lián),如果選擇不關(guān)聯(lián)也可以应役,后面后說道如果關(guān)聯(lián)情组,因?yàn)槲沂堑诙蝿?chuàng)建,所以就默認(rèn)執(zhí)行了之前選擇的箩祥。

上面都執(zhí)行完畢后在本地就會(huì)生成一個(gè)項(xiàng)目院崇,名稱就是剛輸入的flutter_lib

3、編譯flutter_lib項(xiàng)目袍祖,下載配置gradle底瓣,如果是android studio 直接打開項(xiàng)目也可以

依次執(zhí)行下面命令,第一個(gè)命令是進(jìn)入到項(xiàng)目根目錄

cd flutter_lib

flutter build apk


4蕉陋、如果初始化的時(shí)候沒有關(guān)聯(lián)native項(xiàng)目捐凭,則在原生項(xiàng)目根目錄下運(yùn)行下面命令進(jìn)行關(guān)聯(lián)、如果初始化時(shí)已經(jīng)關(guān)聯(lián)則跳過此步驟凳鬓。
進(jìn)入native項(xiàng)目根目錄執(zhí)行:flutter-boot link "flutter項(xiàng)目的本地目錄"茁肠,link后面為flutter項(xiàng)目本地目錄


重新關(guān)聯(lián):flutter-boot link -f "flutter項(xiàng)目的本地目錄"

這一步是將原生項(xiàng)目與flutter項(xiàng)目進(jìn)行軟關(guān)聯(lián),這一步執(zhí)行完畢已經(jīng)就可以進(jìn)行正常的混合開發(fā)了

5缩举、使用flutter_boost垦梆,添加混合棧

執(zhí)行:flutter-boot use

flutter-boot use
這一步執(zhí)行完畢匹颤,會(huì)在原生項(xiàng)目的app下build.gradle、settings.gradle和gradle.properties文件中生成一些配置信息奶赔,具體如下

gradle.properties文件


settings.gradle文件

app下build.gradle文件


除了以上增加的內(nèi)容外惋嚎,還會(huì)多出來兩個(gè)gradle文件,分別是flutter的build.gradle和flutter-boost的build.gradle文件站刑;他們分別對(duì)應(yīng)flutter_lib(flutter側(cè))和flutter_boost庫的gradle配置另伍,一般情況下不要去修改這兩個(gè)文件中的內(nèi)容,否則會(huì)引起一些編譯錯(cuò)誤绞旅。

6摆尝、初始化flutter-boost

執(zhí)行完flutter-boot use 命令后分別會(huì)在native側(cè)和flutter側(cè)的項(xiàng)目根目錄下生成一些初始化使用的事例代碼,可以參考因悲;native側(cè)的在 fb目錄下堕汞,flutter的在main.dart和my_flutter_boost_app.dart文件中。

Native側(cè)我把生成的事例代碼進(jìn)行了整理晃琳,首先是Application中的初始化部分:FlutterInitializer.init(this);

public class App extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        FlutterInitializer.init(this);
    }
}

FlutterInitializer.java的部分

public class FlutterInitializer {
    private final static String TAG = FlutterInitializer.class.getSimpleName();
 
 
    public static void init(Application app) {
        if (!(app instanceof FlutterApplication)) {
            FlutterMain.startInitialization(app);
        }
 
        //路由,Flutter 啟動(dòng)Native頁面的時(shí)候回調(diào)這里
        INativeRouter router = (context, url, urlParams, requestCode, exts) -> {
            String assembleUrl = Utils.assembleUrl(url, urlParams);
            PageRouter.openPageByUrl(context, assembleUrl, urlParams);
        };
        //插件注冊(cè)
        FlutterBoost.BoostPluginsRegister pluginsRegister = mRegistry -> {
            GeneratedPluginRegistrant.registerWith(mRegistry);
            //注冊(cè)native的TextView插件讯检,插件名稱:TextPlatformViewPlugin
            TextPlatformViewPlugin.register(mRegistry.registrarFor("TextPlatformViewPlugin"));
        };
        //配置
        Platform platform = new FlutterBoost.ConfigBuilder(app, router)
                .isDebug(true)
                .whenEngineStart(FlutterBoost.ConfigBuilder.ANY_ACTIVITY_CREATED)
                .renderMode(FlutterView.RenderMode.texture)
                .pluginsRegister(pluginsRegister)
                .build();
 
        //初始化flutter_boost
        FlutterBoost.instance().init(platform);
    }
}

PageRouter.java:是一個(gè)自定義的路由控制輔助類,方便管理頁面跳轉(zhuǎn)

public class PageRouter {
 
    public final static Map<String, String> pageName = new HashMap<String, String>() {{
 
        put("first", "first");
        put("second", "second");
        put("tab", "tab");
        put("sample://flutterPage", "flutterPage");
        put("sample://demoFlutterPage", "flutterDemoPage");
    }};
 
    public static final String NATIVE_PAGE_URL = "sample://nativePage";
 
    public static final String FLUTTER_DEMO_PAGE_URL = "sample://demoFlutterPage";
    public static final String FLUTTER_PAGE_URL = "sample://flutterPage";
    public static final String FLUTTER_FRAGMENT_PAGE_URL = "sample://flutterFragmentPage";
 
    public static boolean openPageByUrl(Context context, String url, Map params) {
        return openPageByUrl(context, url, params, 0);
    }
 
    public static boolean openPageByUrl(Context context, String url, Map params, int requestCode) {
 
        String path = url.split("\\?")[0];
 
        Log.i("openPageByUrl", path);
 
        try {
            if (pageName.containsKey(path)) {
                //打開指定url的flutter頁面
                Intent intent = BoostFlutterActivity.withNewEngine().url(pageName.get(path)).params(params)
                        .backgroundMode(BoostFlutterActivity.BackgroundMode.opaque).build(context);
                if (context instanceof Activity) {
                    Activity activity = (Activity) context;
                    activity.startActivityForResult(intent, requestCode);
                } else {
                    context.startActivity(intent);
                }
                return true;
            } else if (url.startsWith(FLUTTER_FRAGMENT_PAGE_URL)) {
                //打開flutter創(chuàng)建的fragment
                context.startActivity(new Intent(context, FlutterFragmentPageActivity.class));
                return true;
            } else if (url.startsWith(NATIVE_PAGE_URL)) {
                //打開原生Activity
                context.startActivity(new Intent(context, NativePageActivity.class));
                return true;
            }
            return false;
        } catch (Throwable t) {
            return false;
        }
    }
}

flutter側(cè)的代碼我整理到lib下了卫旱,具體如下

main.dart文件人灼,我自己在生成的事例代碼上添加了自己的一些邏輯

void main() => runApp(MyFlutterBoostApp({
      'embeded': (pageName, params, String id) => EmbededFirstRouteWidget(),
      'first': (pageName, params, String id) => FirstRouteWidget(),
      'second': (pageName, params, String id) => SecondRouteWidget(),
      'tab': (pageName, params, String id) => TabRouteWidget(),
      'platformView': (pageName, params, String id) => PlatformRouteWidget(),
      'flutterDemoPage': (String url, Map params, String id) =>
          MyHomePage(title: '$url $id'),
      'flutterPage': (String pageName, Map params, String id) =>
          FlutterRouteWidget(params: params),
      'flutterFragment': (String url, Map params, String id) =>
          FragmentRouteWidget(params),
    }));
my_flutter_boost_app.dart文件

class MyFlutterBoostApp extends StatefulWidget {
  final Map<String, PageBuilder> builders;
 
  MyFlutterBoostApp(this.builders);
 
  @override
  _MyFlutterBoostAppState createState() => _MyFlutterBoostAppState();
}
 
class _MyFlutterBoostAppState extends State<MyFlutterBoostApp> {
  @override
  void initState() {
    super.initState();
    FlutterBoost.singleton.registerPageBuilders(widget.builders);
  }
 
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      builder: FlutterBoost.init(postPush: _onRoutePushed),
      home: Container(),
    );
  }
 
  void _onRoutePushed(
    String pageName,
    String uniqueId,
    Map params,
    Route route,
    Future _,
  ) {
    print("flutter端路由:pageName:$pageName\n params:$params\n route:$route");
  }
}

核心代碼為: FlutterBoost.singleton.registerPageBuilders(widget.builders)這句,flutter-boost注冊(cè)一個(gè)flutter 的widget供native側(cè)通過url來調(diào)用顾翼。

7投放、manifest文件的配置

必須注冊(cè)這個(gè)activity,否則無法打開flutter頁面

 <!--        這個(gè)必須注冊(cè)适贸,不然無法打開flutter的頁面-->
        <activity
            android:name="com.idlefish.flutterboost.containers.BoostFlutterActivity"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
            android:hardwareAccelerated="true"
            android:screenOrientation="portrait"
            android:theme="@style/Theme.AppCompat"
            android:windowSoftInputMode="adjustResize">
            <meta-data
                android:name="io.flutter.embedding.android.SplashScreenDrawable"
                android:resource="@drawable/page_loading" />
 
        </activity>

在每個(gè)需要使用flutter頁面的activity中都要加入android:hardwareAccelerated="true"這個(gè)屬性的配置

8灸芳、如果native項(xiàng)目出現(xiàn)support庫重復(fù)的情況拜姿,可以在項(xiàng)目的build.gradle文件中加入以下代碼來排除重復(fù)包

def addRepos(RepositoryHandler handler) {
    handler.google()
    handler.jcenter()
    handler.maven { url "https://jitpack.io" }
}
 
allprojects {
    //循環(huán)所有依賴烙样,指定support的版本為28.0.0,解決重復(fù)包問題
    //此方法在編譯的時(shí)候會(huì)循環(huán)依賴蕊肥,所以會(huì)增加編譯時(shí)間误阻。建議在
    //依賴的時(shí)候使用exclude 方法排除可能重復(fù)的包
    addRepos(repositories)
    subprojects {
        project.configurations.all {
            resolutionStrategy.eachDependency { details ->
                if (details.requested.group == 'com.android.support'
                        && !details.requested.name.contains('multidex')) {
                    details.useVersion "28.0.0"
                }
            }
        }
    }
}

以上就是flutter-boot混合項(xiàng)目腳手架的使用以及flutter-boost的配置了,每一步都是本人自己通過動(dòng)手實(shí)踐驗(yàn)證過的晴埂,如過程中有錯(cuò)誤,首頁確認(rèn)以下flutter版本和使用的flutter-boost的版本寻定,版本對(duì)應(yīng)關(guān)系以flutter-boost官網(wǎng)介紹為準(zhǔn)https://github.com/alibaba/flutter_boost儒洛。

簡(jiǎn)易MVP,支持Jetpack:https://blog.csdn.net/qq_19979101/article/details/103691091

Flutter中Sqlite使用:https://blog.csdn.net/qq_19979101/article/details/93030803

Flutter的Stomp-websocket插件:https://blog.csdn.net/qq_19979101/article/details/93873731

原文作者:與猿同行
原文鏈接:https://blog.csdn.net/qq_19979101/article/details/103777979

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末狼速,一起剝皮案震驚了整個(gè)濱河市琅锻,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖恼蓬,帶你破解...
    沈念sama閱讀 218,525評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件惊完,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡处硬,警方通過查閱死者的電腦和手機(jī)小槐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來荷辕,“玉大人凿跳,你說我怎么就攤上這事〈剑” “怎么了控嗜?”我有些...
    開封第一講書人閱讀 164,862評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)骡显。 經(jīng)常有香客問我疆栏,道長(zhǎng),這世上最難降的妖魔是什么惫谤? 我笑而不...
    開封第一講書人閱讀 58,728評(píng)論 1 294
  • 正文 為了忘掉前任壁顶,我火速辦了婚禮,結(jié)果婚禮上石挂,老公的妹妹穿的比我還像新娘博助。我一直安慰自己,他們只是感情好痹愚,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,743評(píng)論 6 392
  • 文/花漫 我一把揭開白布富岳。 她就那樣靜靜地躺著,像睡著了一般拯腮。 火紅的嫁衣襯著肌膚如雪窖式。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,590評(píng)論 1 305
  • 那天动壤,我揣著相機(jī)與錄音萝喘,去河邊找鬼。 笑死琼懊,一個(gè)胖子當(dāng)著我的面吹牛阁簸,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播哼丈,決...
    沈念sama閱讀 40,330評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼启妹,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了醉旦?” 一聲冷哼從身側(cè)響起饶米,我...
    開封第一講書人閱讀 39,244評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤桨啃,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后檬输,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體照瘾,經(jīng)...
    沈念sama閱讀 45,693評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,885評(píng)論 3 336
  • 正文 我和宋清朗相戀三年丧慈,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了析命。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,001評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡伊滋,死狀恐怖碳却,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情笑旺,我是刑警寧澤昼浦,帶...
    沈念sama閱讀 35,723評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站筒主,受9級(jí)特大地震影響关噪,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜乌妙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,343評(píng)論 3 330
  • 文/蒙蒙 一使兔、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧藤韵,春花似錦虐沥、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至匹涮,卻和暖如春天试,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背然低。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工喜每, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人雳攘。 一個(gè)月前我還...
    沈念sama閱讀 48,191評(píng)論 3 370
  • 正文 我出身青樓带兜,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親吨灭。 傳聞我的和親對(duì)象是個(gè)殘疾皇子鞋真,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,955評(píng)論 2 355

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