開發(fā)集成環(huán)境
[?] Flutter (Channel stable, v1.12.13+hotfix.9, on Mac OS X 10.14.6 18G103, locale zh-Hans-CN)
接觸使用Flutter也有段時間了摔竿,利用假期來梳理下在Flutter在使用層面的一些混編知識點诬留,其實整理起來會發(fā)現(xiàn)
原生與Flutter的混編
和原生與RN的混編
相似度很大蝗砾,其實所有的跨平臺框架談到和原生混編核心也就是方法調(diào)用和消息通信日熬,自然很相似了,這里簡單列以下幾點(前幾點方便你前期技術(shù)調(diào)研方案可行性研究盆繁,便于你快速去創(chuàng)建demo落實到項目中進行試手掀淘,后期再逐步梳理Dart語法筆記以及Flutter開發(fā)中的筆記)(這里就不講述Flutter的環(huán)境搭建了)
:
一、簡述Flutter集成到Android原生項目
二油昂、Android原生以AAR形式集成Flutter項目
三革娄、Flutter與原生(Android/IOS)的消息通信
四、Flutter中如何使用原生控件/組件
五冕碟、Flutter狀態(tài)管理Provider與Redux
六拦惋、Flutter升級及開發(fā)中遇到的問題匯總
在現(xiàn)有Android項目中集成Flutter項目,可參考官網(wǎng)方法Add Flutter to existing app安寺。
當然也可按照下列步驟操作即可厕妖。
1、 新建Flutter項目,選擇Flutter Module類型
- 通過Android Studio 選擇
File
->New
->New Flutter Project
->Flutter Module
創(chuàng)建挑庶。 - 通過命令行
$ flutter create -t module my_flutter
創(chuàng)建言秸。
創(chuàng)建完成后,F(xiàn)lutter Module可正常運行到設(shè)備上迎捺。
2井仰、 在Android項目中集成Flutter項目
在宿主項目app下的的 build.gradle
里面,android {} 下修改:
android {
//...
compileOptions {
sourceCompatibility 1.8
targetCompatibility 1.8
}
}
如何在原生項目中引入Flutter模塊
方式一:主module通過模塊依賴方式來依賴flutter
將flutter作為module破加,然后native主工程引入進來。這種方式適合參與人數(shù)比較少的項目雹嗦,如果有多人協(xié)作開發(fā)的大型項目就不合適了范舀,因為其他人首先要配置Flutter環(huán)境合是,而且團隊里面其他人還要配置module的依賴,都要熟悉flutter锭环,成本是很高的聪全。
-
在工程的settings.gradle增加以下配置:
// 加入下面配置 setBinding(new Binding([gradle: this])) evaluate(new File( settingsDir.parentFile, 'my_flutter/.android/include_flutter.groovy' //更改成自己的項目目錄 ))
- 在app 的gradle里添加依賴:
弊端:implementation project(':my_flutter')
這種方式適合參與人數(shù)比較少的項目,如果有多人協(xié)作開發(fā)的大型項目就不合適了辅辩,因為其他人首先要配置Flutter環(huán)境难礼,而且團隊里面其他人還要配置module的依賴,都要熟悉flutter玫锋,成本是很高的蛾茉。所以還需要以依賴jar/aar的方式來集成。
方式二:通過aar包引入
-
將Flutter module打包成aar文件:
進入根目錄下的.android目錄下執(zhí)行./gradlew assembleRelease
編譯成功后會在.android/Flutter/build/outputs/aar/flutter-release.aar
生成aar文件撩鹿。 (此種方式生成的aar包之前還能用谦炬,當前版本會報錯,稍后會提供通過使用fat-aar使用腳本打包方式)
注意:暫時以第一種方式集成节沦,稍后在【二键思、Android原生以AAR形式集成Flutter項目】 會詳細講解方式二的使用。
3甫贯、在Android項目中加載Flutter頁面:
-
繼承FlutterActivity加載Flutter頁面
如果初期只是為了加載出對應的Flutter頁面吼鳞,簡單點可不繼承FlutterActivity
創(chuàng)建自己的Activity,可直接使用FlutterActivity
叫搁。
此處的FlutterActivity使用的是public class MyFlutterActivity extends FlutterActivity { // 定義Channel名稱 private static final String CHANNEL_NATIVE = "com.cc.flutter/native"; public static void openFlutter(Activity activity, String routerUrl){ Intent intent = MyFlutterActivity.withNewEngine() .initialRoute(routerUrl) .build(activity); //設(shè)置Activity透明 //intent.putExtra("background_mode","transparent"); activity.startActivity(intent); } public static CCEngineIntentBuilder withNewEngine() { return new CCEngineIntentBuilder(MyFlutterActivity.class); } public static CCEngineIntentBuilder withNewEngine(Class<? extends FlutterActivity> activityClass) { return new CCEngineIntentBuilder(activityClass); } public static class CCEngineIntentBuilder extends NewEngineIntentBuilder { protected CCEngineIntentBuilder(Class<? extends FlutterActivity> activityClass) { super(activityClass); } } @Override public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) { GeneratedPluginRegistrant.registerWith(flutterEngine); //此處是Flutter與原生通信方法赔桌,暫時可不關(guān)注 MethodChannel methodChannel = new MethodChannel(flutterEngine.getDartExecutor(), CHANNEL_NATIVE); methodChannel.setMethodCallHandler(new MethodChannel.MethodCallHandler() { @Override public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) { System.out.println("MethodChannel call.method:"+call.method+ " call arguments:"+call.arguments.toString()); switch (call.method){ case "envType": result.success(2); break; default: result.error("404", "未匹配到對應的方法"+call.method, null); } } }); }
import io.flutter.embedding.android.FlutterActivity;
而不是io.flutter.app.FlutterActivity
, 貌似是說為了更好地支持將 Flutter 添加到現(xiàn)有項目的執(zhí)行環(huán)境,托管 Flutter 運行時的舊版 Android 平臺端包裝器位于io.flutter.app.FlutterActivity
及其關(guān)聯(lián)的類現(xiàn)在已棄用常熙。新的包裝器io.flutter.embedding.android.FlutterActivity
及相關(guān)類替代了他們纬乍。
其實Flutter 1.2升級了很多東西,具體可參考 Upgrading pre 1.12 Android projects 一步步操作裸卫。(稍后我也會梳理在開發(fā)中需要操作的升級點及碰到的問題
) -
AndroidManifest注冊Activity:
<!--flutter相關(guān) start--> <activity android:name=".activity.flutter.MyFlutterActivity" android:launchMode="singleTop" android:screenOrientation="portrait" android:windowSoftInputMode="adjustPan" /> <activity android:name="io.flutter.embedding.android.FlutterActivity" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" android:hardwareAccelerated="true" android:theme="@style/AppTheme" android:windowSoftInputMode="adjustResize" > </activity> <meta-data android:name="flutterEmbedding" android:value="2" /> <!--flutter相關(guān) end-->
-
Flutter中添加如下代碼:
import 'dart:ui'; import 'package:flutter/material.dart'; void main() => runApp(_widgetForRoute(window.defaultRouteName)); Widget _widgetForRoute(String route) { switch (route) { case 'route1': return MaterialApp( debugShowCheckedModeBanner: false, home: Scaffold( appBar: AppBar( title: Text('MyFlutter頁面'), centerTitle: true, ), body: Center( child: Column( children: <Widget>[ Text('Flutter頁面仿贬,route=$route, params=$paramsJson'), RaisedButton( textColor: Colors.blue, child: Text("跳轉(zhuǎn)原生頁面"), onPressed:(){ // 跳轉(zhuǎn)原生頁面 Map<String, dynamic> result = {'name': '你好,${params["name"]}'}; nativeChannel.invokeMethod('jumpToNative', result); }, ), ], ), ), ), ); default: return Center( child: Text('Unknown route: $route', textDirection: TextDirection.ltr), ); } }
以上是Android原生項目中集成Flutter步驟墓贿。
這樣就實現(xiàn)了 Android 原生跳轉(zhuǎn)到 Flutter 頁面進行渲染, 可以邊開發(fā)茧泪,邊編譯看效果了。
注意:文中暫時以第一種方式集成聋袋,稍后在【二队伟、Android原生以AAR形式集成Flutter項目】 會詳細講解方式二的使用。