之前用fluro
替代Flutter自带的Navigation实现一些路由操作,但是Native页面和Flutter页面的一些交互并没有完成,昨天花了些时间集成了安卓模块的flutter_boost
,这边把碰到的问题和一些经历整合一下分享给大家,方便大家快速集成。
项目地址:https://github.com/alibaba/flutter_boost
博客地址:闲鱼技术
因为闲鱼团队这边已经做实现方法和思路的一些分析,所以本文就不会再去抄读一遍,建议大家自行阅读。
Flutter相关的集成操作在原项目的readme中已经详细列出了,我这里只针对Native部分做一些介绍
//主业务页面需要继承BoostFlutterActivity才能使用其中的代理类FlutterContent
public class MainActivity extends BoostFlutterActivity {
}
如果你有自己的封装类建议可以先继承BoostFlutterActivity
再自行实现,集成链路举例如下
MainActivity–>MyBoostFlutterActivity–>FlutterActivity–>Activity
继承这个类之后必须实现
//用于实现Flutter实现,新创建的Flutter项目的onCreate方法里也会有 GeneratedPluginRegistrant.registerWith(this);方法
void onRegisterPlugins(PluginRegistry registry);
//对应Flutter部分组建名(这个名字需要静态注册)
@Override
public abstract String getContainerName();
//Native和Flutter互相传参时可以在这里返回一个任意类型的map,Flutter端对应的是Map params类型的对象
@Override
public abstract Map getContainerParams();
Native业务开这个Activity和打开其他Activity一样只需要用Intent开就行,如果要传参数就.putExtra()传就行。用ARouter
或者DeepLink
实现跳转的使用体验会更好,这个在Flutter跳转Native时再提。
实现这三个方法,我们的容器Activity就完成了。
所有的消息都会在Application里通过IPlatform借口做分发,所以我们需要在application里进行一些初始化和页面跳转分发的逻辑
public class MyApplication extends FlutterApplication {
@Override
public void onCreate() {
super.onCreate();
//初始化Flutter插件并实现回调
FlutterBoostPlugin.init(new IPlatform() {
@Override
public Application getApplication() {
return MyApplication.this;
}
/**
* 获取应用入口的Activity,这个Activity在应用交互期间应该是一直在栈底的
* @return
*/
@Override
public Activity getMainActivity() {
return MainActivity.sRef.get();
}
@Override
public boolean isDebug() {
return true;
}
/**
* 如果flutter想打开一个本地页面,将会回调这个方法,页面参数将会拼接在url中
*
* 例如:sample://nativePage?aaa=bbb
*
* 参数就是类似 aaa=bbb 这样的键值对
*
* @param context
* @param url
* @param requestCode
* @return
*/
@Override
public boolean startActivity(Context context, String url, int requestCode) {
Log.d("---> MyApplication","startActivity url "+url);
return PageRouter.openPageByUrl(context,url,requestCode);
}
@Override
public Map getSettings() {
return null;
}
});
}
}
继承FlutterApplication的主要目的是在onCreate里调用FlutterMain.startInitialization(this);
所以你也可以自己实现该方法,那就爱继承谁都行了。
@override
void initState() {
super.initState();
//初始化Flutter页面自身的一些路由,我的sample里使用的是fluro
final router = new Router();
Routes.configureRoutes(router);
Application.router = router;
//注册Native返回的key与Flutter页面的对应Map
FlutterBoost.singleton.registerPageBuilders({
///可以在native层通过 getContainerParams 来传递参数
'homePage': (pageName, params, _) => renderHome(pageName, params, _),
});
//取最上面的一个页面为首屏页面,而不是 Widget build(BuildContext context) {}内所返回的Widget
FlutterBoost.handleOnStartPage();
}
入口页完整代码
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
State createState() {
return MyAppState();
}
}
class MyAppState extends State {
@override
void initState() {
super.initState();
final router = new Router();
Routes.configureRoutes(router);
Application.router = router;
FlutterBoost.singleton.registerPageBuilders({
///可以在native层通过 getContainerParams 来传递参数
'homePage': (pageName, params, _) => renderHome(pageName, params, _),
});
FlutterBoost.handleOnStartPage();
}
Widget renderHome(String pageName, Map params, String _) {
print("---> pageName " + pageName);
return HomePage();
}
@override
Widget build(BuildContext context) {
final app = MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
primaryColor: Colors.white,
),
builder: FlutterBoost.init(postPush: _onRoutePushed),
home: Container(),
onGenerateRoute: Application.router.generator,
);
return app;
}
void _onRoutePushed(
String pageName, String uniqueId, Map params, Route route, Future _) {
print('---> _onRoutePushed pageName ' + pageName);
}
}
1.Native跳Flutter
触发跳转的地方
Intent intent=new Intent(context, MainActivity.class);
intent.putExtra("key","你要传的参数");
context.startActivity(intent);
Flutter容器内
@Override
public Map getContainerParams() {
//params of the page
Map params = new HashMap<>();
params.put("key",getIntent().getStringExtra("key"));
return params;
}
Flutter main.dart
//homePage是你关联的Key名字getContainerParams()给的map会在params里
'homePage': (pageName, params, _) => renderHome(pageName, params, _),
FlutterBoost.singleton.openPage("原生页面的key", {
"query": {"key": "value"}//你的业务数据,不需要的话传{}
});
Flutter跳Flutter直接就用Navigation跳就完了。
Native跳转Flutter的跳转过程:
Native页面—>Flutter容器—>容器装载Flutter插件–>Flutter根据对应关系选择对应的Flutter Widget
Flutter跳转Native的跳转过程
openPage方法发送消息–>IPlatform的startActivity方法接收到拼接成数据串的url—>经过逻辑处理打开对应的Native页面
为什么之前说用路由库或者DeepLink会更好做是因为,处理完Native收到的url可以直接拼接成deepLink或者路由库的路由串 如nio://nativePage/order?aaa=bbb
不会配DeepLink的可以看这个
closeCurPage(Map params) //关闭当前页面
addBoostContainerLifeCycleObserver(
BoostContainerLifeCycleObserver observer)//添加生命周期监听
addBoostNavigatorObserver(BoostNavigatorObserver observer)//添加路由变化监听
addContainerObserver(BoostContainerObserver observer)//添加内容变化监听
closePageForContext(BuildContext context)//关闭容器
closePage(String url, String pageId, Map params,
{bool animated})//关闭指定页面
sample源码地址:https://github.com/ddwhan0123/flutter_tutorial/tree/boost_branch