Flutter 混合开发FlutterBoost Android 接入流程
最近公司开始推行使用Flutter用于移动端开发,忙活了一个多月的Flutter混合开发迭代端午节后准备上线,写下此过程的坑以及一些接入流程,以及Flutter技术。
由于我主业是搞Android开发的,iOS还是个菜鸟,先介绍一下Android混合接入流程
1.创建Flutter module
很多情况下,Flutter的接入都是在原有的移动端项目的基础上接入,这样相对于侵入原有项目弱,并且接入的成本低,风险也低。
flutter create -t module flutter_module
在命令行界面录入即可,最好是和原本的项目在相同的目录下,同级文件夹。我的项目基本是原有项目是一个git仓库,对应的Flutter代码是在另一个git仓库,这样版本管理也是比较好的
2.Android 开始接入
在原有setting.gradle文件末尾的添加一下代码
setBinding(new Binding([gradle: this]))
evaluate(new File(
settingsDir.parentFile,
'/flutter_module/.android/include_flutter.groovy'
))
这样就会引入到对应的Flutter的module资源,对应的编译脚本,Flutter框架已经写好,后续有时间可以读读
在app目录下的build.gradle文件中添加Flutter依赖
implementation project(':flutter')
主要的依赖链如下
flutter_module/.android/include_flutter.groovy ->
flutter_module/.android/Flutter/build.gradle ->
$flutterRoot/packages/flutter_tools/gradle/flutter.gradle
很方便的完成混合开发的打包操作,接入完之后最好在flutter项目下面的.android文件下,用命令行工具执行以下
gradlew assembleDebug
命令完成对应的Android依赖加载
3.原生显示Flutter的视图
Button open = findViewById(R.id.openBtn);
open.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setClass(MainActivity.this, MyFlutterActivity.class);
startActivity(intent);
}
});
public class MyFlutterActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_flutter);
final FlutterView flutterView = Flutter.createView(
this,
getLifecycle(),
"route1"
);
final FrameLayout layout = findViewById(R.id.flutter_container);
layout.addView(flutterView);
}
}
只需要在Activity中的addView即可,看起来很简单,不过存在很多问题,跳转过程可能会有黑屏情况,以及Flutter视图的复用也是个问题,以及对应的Flutter 跳转Native界面也是个问题。于是乎谷歌发现FlutterBoost框架解决了大部分以上的问题。
4.FlutterBoost框架的接入
依照https://github.com/alibaba/flutter_boost官方的文档,接入发现有很多的坑,不知道是不是开发人员都反感写文档一样的。
接入的流程如下:
4.1 Flutter项目接入FlutterBoost
在对应的pubspec.yaml文件中加入依赖,pubspec.yaml就是一个配置文件。
flutter_boost:
git:
url: 'https://github.com/alibaba/flutter_boost.git'
ref: '0.0.411'
之后调用Package get,右上角即可查看,之后还是在.android 文件下执行
gradlew assembleDebug,完成依赖下载。
4.2 Flutter中main.dart文件中配置
@override
void initState() {
super.initState();
FlutterBoost.singleton.registerPageBuilders({
//对应的Page的名字,最好是类Http格式
'demoPage': (pageName, params, _) {
return DemoPage();
},
});
FlutterBoost.handleOnStartPage();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Boost example',
builder: FlutterBoost.init(postPush: _onRoutePushed),
home: Container());
}
void _onRoutePushed(
String pageName, String uniqueId, Map params, Route route, Future _) {}
4.3 Android 中的Application的设置
@Override
public void onCreate() {
super.onCreate();
initFlutterBoot();
}
private void initFlutterBoot() {
FlutterBoostPlugin.init(new IPlatform() {
@Override
public Application getApplication() {
return mApplication;
}
@Override
public Activity getMainActivity () {
//这里返回null,可以避免跳转界面的(MainActivity)的页面整体上移
return null;
}
@Override
public boolean isDebug() {
return AppConfig.IS_DEVELOPING;
}
@Override
public boolean startActivity(Context context, String url, int requestCode) {
//Flutter 跳转的回调
return PageRouter.openPageByUrl(context,url,requestCode);
}
@Override
public Map getSettings() {
return null;
}
});
}
坑1:getMainActivity 如果返回MainActivity,会导致对应的主页面的布局整体上移,发现给null也没啥问题。
4.4 Native和Flutter界面的跳转
Native–>Fluuter
可以使用官方Demo中的PageRouter
public class PageRouter {
public static final String COMMISSION_TASK_PAGE = "gamma://flutter/commissionTaskPage";
public static final String NATIVE_CUST_INFO_PAGE_URL = "gamma://native/custInfo";
public static boolean openPageByUrl(Context context, String url) {
return openPageByUrl(context, url, 0, "{}");
}
public static boolean openPageByUrl(Context context, String url, String json) {
return openPageByUrl(context, url, 0, json);
}
public static boolean openPageByUrl(Context context, String url, int requestCode) {
return openPageByUrl(context, url, requestCode, "{}");
}
public static boolean openPageByUrl(Context context, String url, int requestCode, String json) {
try {
if (url.startsWith(COMMISSION_TASK_PAGE)) {
//贷后任务
Intent intent = new Intent(context, FlutterPageActivity.class);
intent.putExtra("pageName", "gamma://flutter/commissionTaskPage");
intent.putExtra("json", json);
context.startActivity(intent);
return true;
} else if (url.contains(NATIVE_CUST_INFO_PAGE_URL)) {
//打开客户界面
Map<String, String> params = getUrlParams(url);
AppUIHelper
.showCustomerInfoActivity(context, params.get("custId"));
return true;
}
} catch (Throwable t) {
return false;
}
}
//获取对应url中的参数
private static Map getUrlParams(String url) {
Map<String, Object> map = new HashMap<>();
url = url.replace("?", ";");
if (!url.contains(";")) {
return map;
}
if (url.split(";").length > 0) {
String[] arr = url.split(";")[1].split("&");
for (String s : arr) {
String key = s.split("=")[0];
String value = s.split("=")[1];
map.put(key, value);
}
return map;
} else {
return map;
}
}
}
这样相对于好管理,Native页面可以设置以Native开头,Flutter以flutter开头,这样好区分。
对应的FlutterPageActivity可以根据官方Demo自行修改。
坑2:FlutterPageActivity中最好加上以下代码
@Override
protected void onCreate(Bundle savedInstanceState) {
FlutterMain.startInitialization(this);
super.onCreate(savedInstanceState);
}
不然会运行报错
Flutter – >Native
这种类型跳转和Activity之间互相跳转有点类似
FlutterBoost.singleton.openPage(
"${NativeUrl.NATIVE_CUST_INFO}?custId=${custId};",
{});
这中类型的跳转会回调到前面Application中的 FlutterBoostPlugin.init 方法中的startActivity方法中,只会在用PageRouter来接收即可。
之后自行做界面的跳转
5.打包的坑
在打release包的时候需要在Flutter的跟目录下执行以下命令
flutter build apk
之后是常规的Android的打包,不然打包出来的apk跳转到Flutter页面就会闪退
推荐阅读
-
Flutter 混合开发FlutterBoost Android 接入流程
-
Flutter与Native混合开发-FlutterBoost集成应用和开发实践(iOS)
-
Flutter混合开发 如何将Flutter项目变成Module导入Android项目(4.6)
-
Flutter—Android混合开发之下载安装的实现
-
FLutter混合开发 Android跳转Flutter页面,Flutter引擎等
-
视频直播软件开发:Android客户端接入谷歌支付的实现流程
-
Flutter混合开发 如何将Flutter项目变成Module导入Android项目(4.6)
-
Flutter与Native混合开发-FlutterBoost集成应用和开发实践(iOS)
-
Flutter—Android混合开发之下载安装的实现
-
FLutter混合开发 Android跳转Flutter页面,Flutter引擎等