Flutter混合开发:Android中如何启动Flutter
目錄
現(xiàn)有項(xiàng)目中引入Flutter
啟動(dòng)flutter頁面
加速啟動(dòng)
啟動(dòng)傳參
?
flutter可以獨(dú)立完成項(xiàng)目,但是在現(xiàn)有項(xiàng)目情況下最好的方式就是混合開發(fā),逐步過渡。這樣就會(huì)共存native和flutter代碼,而其中最關(guān)鍵的就是native如何啟動(dòng)flutter頁面,及flutter與native如何交互。
本文以Android為例,展示如何在一個(gè)現(xiàn)有項(xiàng)目中引入flutter、啟動(dòng)flutter,如何加速啟動(dòng)以及如何傳參。
現(xiàn)有項(xiàng)目中引入Flutter
在現(xiàn)有的Android項(xiàng)目中,新建一個(gè)flutter module。創(chuàng)建完module后會(huì)發(fā)現(xiàn)自動(dòng)在主module中依賴了。當(dāng)然我們?nèi)绻渌?xiàng)目使用該flutter模塊,并不會(huì)自動(dòng)進(jìn)行這一步,所以要先在setting.gradle中注冊(cè),如下:
setBinding(new Binding([gradle: this])) evaluate(new File(settingsDir,'flutter_module/.android/include_flutter.groovy' ))include ':flutter_module'然后在主module中依賴:
implementation project(path: ':flutter')這樣就可以進(jìn)行混合開發(fā)了。
啟動(dòng)flutter頁面
新建flutter module后會(huì)自動(dòng)創(chuàng)建一個(gè)main頁面,那么native如何打開這個(gè)頁面?
首先在主module的manifest中添加:
<activityandroid:name="io.flutter.embedding.android.FlutterActivity"android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"android:hardwareAccelerated="true"android:windowSoftInputMode="adjustResize"/>然后用一下代碼即可打開flutter主頁面
startActivity(FlutterActivity.createDefaultIntent(this))那么如何打開其他頁面?
比如我們創(chuàng)建一個(gè)新的flutter頁面second:
import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart';class SecondPage extends StatefulWidget{@overrideState<StatefulWidget> createState() {return _SecondPage();}}class _SecondPage extends State<SecondPage>{@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("test"),),body:Text("test"));} }然后在main.dart的App下注冊(cè)這個(gè)頁面:
class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(primarySwatch: Colors.blue,),home: MyHomePage(title: 'Flutter Demo Home Page'),routes: {"second" : (BuildContext context) => SecondPage(), //也可以用其他方式注冊(cè)},);} }這樣在flutter中可以用以下代碼打開這個(gè)頁面:
Navigator.of(context).pushNamed("second");而在Android中就可以用以下代碼即可打開該頁面:
startActivity(FlutterActivity.withNewEngine().initialRoute("second").build(this))加速啟動(dòng)
通過上面代碼打開flutter頁面時(shí)會(huì)出現(xiàn)黑屏現(xiàn)象,時(shí)間并不短,很影響體驗(yàn)。因?yàn)槊看味贾匦耼ew一個(gè)flutter engine( createDefaultIntent函數(shù)內(nèi)部其實(shí)也是withNewEngine().build(launchContext) )。
官方給出的解決方案是使用engine cache,比如在Appliation中添加cache:
var flutterEngine = FlutterEngine(this)flutterEngine.dartExecutor.executeDartEntrypoint(DartExecutor.DartEntrypoint.createDefault())FlutterEngineCache.getInstance().put("main", flutterEngine)然后將啟動(dòng)改成:
startActivity(FlutterActivity.withCachedEngine("main").build(this))但是上面僅僅是啟動(dòng)main頁面,如果想啟動(dòng)其他頁面,比如second,就需要繼續(xù)添加cache:
var flutterEngine2 = FlutterEngine(this)flutterEngine2.navigationChannel.setInitialRoute("second")flutterEngine2.dartExecutor.executeDartEntrypoint(DartExecutor.DartEntrypoint.createDefault())FlutterEngineCache.getInstance().put("second", flutterEngine2)注意這里通過setInitialRoute設(shè)置了route。然后啟動(dòng)即可:
startActivity(FlutterActivity.withCachedEngine("second").build(this))通過緩存engine,啟動(dòng)時(shí)黑屏?xí)r間縮短了很多,幾乎不可察覺(注意第一次可能還會(huì)稍微黑屏一下)。
啟動(dòng)傳參
上面我們打開main和second頁面沒有傳參,那么如果想傳入一些初始化必要的參數(shù),如何處理?
目前flutter框架并沒有封裝攜帶參數(shù)的api,也就是說native跳轉(zhuǎn)flutter官方是沒有參數(shù)。但是我們實(shí)際場(chǎng)景又有這樣的需求,怎么處理?
官方?jīng)]有給出相應(yīng)的api,那么只能從route上想辦法。首先改變app中注冊(cè)route的方式,上面直接使用routes這種map的形式,我們換成onGenerateRoute這種RouteFactory形式,如下:
onGenerateRoute: (RouteSettings settings) {if(settings.name.startsWith("second")){return MaterialPageRoute(builder: (BuildContext context) {return SecondPage(settings.name);});}else {return MaterialPageRoute(builder: (BuildContext context) {return Scaffold(body: Center(child: Text("page not found"),),);});}},這里的settings.name就是route,因?yàn)槲覀兿朐趓oute后面添加參數(shù),所以通過開頭來判斷是那個(gè)頁面。
注意:示例中直接將route url傳給頁面,其實(shí)應(yīng)該在這里統(tǒng)一解析出來,以map的形式傳給頁面。
然后修改Second頁面:
class SecondPage extends StatefulWidget{String url;SecondPage(String url){this.url = url;}@overrideState<StatefulWidget> createState() {return _SecondPage();}}class _SecondPage extends State<SecondPage>{@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("test"),),body:Text("test:${widget.url}"));} }這里沒有解析,直接將url展示出來了,目的是參數(shù)傳到位即可。
最后在native使用如下代碼:
startActivity(FlutterActivity.withNewEngine().initialRoute("second?text=second test").build(this))就可以傳遞參數(shù)了。
但是這樣就引出了另外一個(gè)問題,因?yàn)樯厦孢@種啟動(dòng)方式并沒有使用engine cache,如果使用engine cache那么route就必須提前定好以便在Appllication中放入cache中。但是我們既然要傳參,那么說明route是動(dòng)態(tài)改變的,所以這兩個(gè)是沖突的,這樣在傳參的情況下就無法加速啟動(dòng)了么?
?
總結(jié)
以上是生活随笔為你收集整理的Flutter混合开发:Android中如何启动Flutter的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Flutter:Navigator2.0
- 下一篇: Flutter如何与Native(And