简介
在使用flutter混合开发中,免不了flutter和原生native页面的相互跳转和通信,flutterboost就是闲鱼团队开发的一个可复用的插件,旨在把Flutter容器做成浏览器的感觉。填写一个页面地址,然后由容器去管理页面的绘制。在Native侧我们只需要关心如果初始化容器,然后设置容器对应的页面标志即可。
准备工作
- Flutter项目
在pubspec.yaml中添加以下依赖项:
flutter_boost: ^0.0.400
将init代码添加到Dart的app首页面;
void main (){
runApp(App());
}
class App extends StatefulWidget{
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<App>{
@override
void initState() {
// TODO: implement initState
super.initState();
///register page widget builders,the key is pageName
FlutterBoost.singleton.registerPageBuilders({
'first': (pageName, params, _) => FirstRouteWidget(),
'second': (pageName, params, _) => SecondRouteWidget(),
'flutterFragment': (pageName, params, _) => FragmentRouteWidget(params),
///可以在native层通过 getContainerParams 来传递参数
'flutterPage': (pageName, params, _) {
print("flutterPage params:$params");
return FlutterRouteWidget();
},
});
///query current top page and load it
FlutterBoost.handleOnStartPage();
}
@override
Widget build(BuildContext context) =>MaterialApp(
title: "Flutter Boost demo",
builder: FlutterBoost.init(),
home: Container(),
);
}
- Android工程
在Application.onCreate()中初始化FlutterBoost
public class MyApplication extends FlutterApplication {
@Override
public void onCreate() {
super.onCreate();
FlutterBoostPlugin.init(new IPlatform() {
@Override
public Application getApplication() {
return MyApplication.this;
}
/**
* get the main activity, this activity should always at the bottom of task stack.
*/
@Override
public Activity getMainActivity() {
return MainActivity.sRef.get();
}
@Override
public boolean isDebug() {
return false;
}
/**
* start a new activity from flutter page, you may need a activity router.
*/
@Override
public boolean startActivity(Context context, String url, int requestCode) {
return PageRouter.openPageByUrl(context,url,requestCode);
}
@Override
public Map getSettings() {
return null;
}
});
}
里面的PageRouter是在Android本地工程中定义的一个页面路由跳转类,比较简单就是一个根据URL来跳转到指定activity的配置类,代码如下
public class PageRouter {
public static final String NATIVE_PAGE_URL = "sample://nativePage";
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) {
return openPageByUrl(context, url, 0);
}
public static boolean openPageByUrl(Context context, String url, int requestCode) {
try {
if (url.startsWith(FLUTTER_PAGE_URL)) {
context.startActivity(new Intent(context, FlutterPageActivity.class));
return true;
} else if (url.startsWith(FLUTTER_FRAGMENT_PAGE_URL)) {
context.startActivity(new Intent(context, FlutterFragmentPageActivity.class));
return true;
} else if (url.startsWith(NATIVE_PAGE_URL)) {
context.startActivity(new Intent(context, NativePageActivity.class));
return true;
} else {
return false;
}
} catch (Throwable t) {
return false;
}
}
}
IOS平台怎么集成就不介绍了,因为没开发过IOS,如果需要的话可以去咸鱼官方找找怎么集成。
简单解析
首先介绍一下在Dart中使用flutterboost中打开一个页面:
FlutterBoost.singleton.openPage("pagename", {}, true);
关闭页面:
FlutterBoost.singleton.closePageForContext(context);
之前说过在flutterboost中旨在通过一个URL去打过一个页面,不管这个页面是一个flutter页面还是一个native页面,那它是怎么做到的呢?回头看看上面的代码
- 打开Flutter页面
我们可以看到在Dart中创建_MyAppState这个widget的时候有下面这段代码
FlutterBoost.singleton.registerPageBuilders({
'first': (pageName, params, _) => FirstRouteWidget(),
'second': (pageName, params, _) => SecondRouteWidget(),
'flutterFragment': (pageName, params, _) => FragmentRouteWidget(params),
///可以在native层通过 getContainerParams 来传递参数
'flutterPage': (pageName, params, _) {
print("flutterPage params:$params");
return FlutterRouteWidget();
},
});
上面的代码其实就是在将原生的flutter页面注册到flutterboost中,以key,value的形式,其中key就是页面名,value就是目标flutter页面,所以上面的代码在dart中就可以通过"second"这个url来打开SecondRouteWidget这个flutter页面,具体调用代码如下:
body: Center(
child: RaisedButton(
child: Text('Open second page'),
onPressed: () {
FlutterBoost.singleton.openPage("second", {}, animated: true);
},
),
),);
可以看到FlutterBoost就是通过"second"这个url来打开flutter页面的,所以我们可以在一开始的app的widget的定义中把所有的flutter以键值对的形式都注册到FlutterBoost中,在之后就可以通过key来打开相应的flutter页面了。
- 打开native页面
仍然是讲Android的,IOS的可自行百度哈,上面的代码我们在application的oncreate中有初始化FlutterBoostPlugin,里面比较关键的是这个方法:
@Override
public boolean startActivity(Context context, String url, int requestCode) {
Debuger.log("startActivity url="+url);
return PageRouter.openPageByUrl(context,url,requestCode);
}
当在Dart中调用FlutterBoost.singleton.openPage("pagename", {}, true);这个方法打开的页面是一个native页面的时候就会回调到上面的那个方法中,可以看到会传过来一个url,接着就是使用我们自己定义的路由页面PageRouter根据指定的url来打开相应的native页面了。比如下面这样:
public static boolean openPageByUrl(Context context, String url, int requestCode) {
try {
if (url.startsWith(FLUTTER_PAGE_URL)) {
context.startActivity(new Intent(context, FlutterPageActivity.class));
return true;
} else if (url.startsWith(FLUTTER_FRAGMENT_PAGE_URL)) {
context.startActivity(new Intent(context, FlutterFragmentPageActivity.class));
return true;
} else if (url.startsWith(NATIVE_PAGE_URL)) {
context.startActivity(new Intent(context, NativePageActivity.class));
return true;
} else {
return false;
}
} catch (Throwable t) {
return false;
}
}
可以看到在native的Android工程中就是根据FlutterBoost传回来的url来打开指定的activity的。其实现在有个问题,我们看到原生的flutter页面有在FlutterBoost注册,然后才能根据注册的url找到对应的flutter页面,那么native页面在哪注册的呢?FlutterBoost又是怎么根据url知道这是一个native页面呢?
其实在native的activity中需要继承BoostFlutterActivity然后实现getContainerName()方法,这个方法返回的url就是注册在FlutterBoost中的key
@Override
public String getContainerName() {
return "flutterPage";
}
这样在Dart中就可以通过"flutterPage"这个url来打开这个native的页面了。当然除了要实现getContainerName()这个方法外,如果你的native页面需要跟flutter页面通信的话还需要实现getContainerParams(),这个方法返回一个map对象,里面存的键值对可以传给原生的flutter页面。
@Override
public Map getContainerParams() {
Map<String,String> params = new HashMap<>();
params.put("aaa","bbb");
return params;
}
结语
关于FlutterBoost的介绍就这么多了,写的还算简单,权当笔记,以备后面忘了的话可以再翻翻~