使用Flutter_Boost进行混合开发-Android
- 创建Flutter项目,用 flutter create -t module fluttr_test 命令来创建,flutter_test为我们的Flutter的工程名
用Android studio打开刚才创建的功能,我们刚创建好的时候不会有.android与.ios这两个目录的,用Android studio打开构建一下就出来了(也可以用flutter make-host-app-editable命令来创建出来),.android与.ios中都存在一个Flutter目录,这个很重要,我试过只有通过flutter create -t module XXX命令生成出来的才有这个Flutter的文件夹,直接创建出来的没有,Flutter这个是我们flutter的库项目,Android用来生成aar,iOS用来生成framework
2.接下来就是依赖了,添加flutter的依赖
这里要注意层级关系,要和flutter:一个层级
flutter_boost: ^0.0.415
添加完依赖后,在flutter中初始化flutter_boost,配置路由
import 'package:flutter/material.dart';
import 'package:flutter_boost/flutter_boost.dart';
import 'package:fluttr_test/firstpage.dart';
import 'package:fluttr_test/second.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyApp> {
@override
void initState() {
// TODO: implement initState
super.initState();
FlutterBoost.singleton.registerPageBuilders({
'first':(pageName,params,_){//格式为路由名称:(pageName,params,_)pageName是路由名称,params为原生传递过来的参数
return FirstPage();//返回一个widget
},
'second':(pageNmae,params,_){
return Second();
},
});
FlutterBoost.handleOnStartPage();//查询当前的顶层页面,并加载它
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'oa',
builder: FlutterBoost.init(),
home: Container(),
);
}
}
- flutter配置完了,接下来就是配置Android
- settings.gradle中添加,这里我是把flutter_test工程放在和Android工程同一级目录下的(是与project同一级,不是与module同一级),这里如果报文件找不到那就是你的路径写错了,重新检查一下路径
这里切记flutter一定要生成出.android与.ios两个文件
setBinding(new Binding(gradle:this))
evaluate(new File('../flutter_test/.android/include_flutter.groovy'))
- app.gradle中配置flutter与flutter_boost
implementation project(path:':flutter')
implementation project(":flutter_boost")
- Application中进行初始化
FlutterMain.startInitialization(this);
FlutterBoostPlugin.init(new IPlatform() {
@Override
public Application getApplication() {
return FunnyApplication.this;
}
/**
* 获取应用入口的Activity,这个Activity在应用交互期间应该是一直在栈底的
* @return
*/
@Override
public Activity getMainActivity() {
if (MainActivity.sRef != null) {
return MainActivity.sRef.get();
}
return null;
}
@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) {
Debuger.log("startActivity url="+url);
return PageRouter.openPageByUrl(context,url,requestCode);
}
@Override
public Map getSettings() {
return null;
}
});
- flutter与Android的初始化都完成了,接下来就是完成我们的混合需求,我们考虑五种情况:Android跳转到flutter页面,flutter跳转到Android页面,Android中嵌入Flutter界面、Flutter中嵌入Android界面、一个原生界面中同时有flutter界面与原生界面
- Android跳转到flutter页面:
- 创建一个activity,继承BoostFlutterActivity,我们主要关注的主要有两个方法,getContainerName(),getContainerParams();
getContainerName()配置对应key,就是我们在flutter中配置路由的key;
getContainerParams()配置我们要传递给flutter页面的数据;
然后直接跳转到这个activity就行了startActivity(new Intent(getActivity(), FlutterPageActivity.class));
- 创建一个activity,继承BoostFlutterActivity,我们主要关注的主要有两个方法,getContainerName(),getContainerParams();
package com.example.funny.flutter;
import com.taobao.idlefish.flutterboost.containers.BoostFlutterActivity;
import java.util.HashMap;
import java.util.Map;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugins.GeneratedPluginRegistrant;
public class FlutterPageActivity extends BoostFlutterActivity {
@Override
public void onRegisterPlugins(PluginRegistry registry) {
GeneratedPluginRegistrant.registerWith(registry);
}
/**
* 该方法返回当前Activity在Flutter层对应的name,
* 混合栈将会在flutter层根据这个名字,在注册的Route表中查找对应的Widget
*
* 在flutter层有注册函数:
* FlutterBoost.singleton.registerPageBuilders({
* 'first': (pageName, params, _) => FirstRouteWidget(),
* 'second': (pageName, params, _) => SecondRouteWidget(),
* ...
* });
*
* 该方法中返回的就是注册的key:first , second
*
* @return
*/
@Override
public String getContainerName() {
return "first";
}
/**
* 该方法返回的参数将会传递给上层的flutter对应的Widget
*
* 在flutter层有注册函数:
* FlutterBoost.singleton.registerPageBuilders({
* 'first': (pageName, params, _) => FirstRouteWidget(),
* 'second': (pageName, params, _) => SecondRouteWidget(),
* ...
* });
*
* 该方法返回的参数就会封装成上面的params
*
* @return
*/
@Override
public Map getContainerParams() {
Map<String,String> params = new HashMap<>();
params.put("aaa","bbb");
return params;
}
}
- flutter跳转到android:
- flutter中直接调用openPage
第一个参数是路由url,我们在Android中要对应上的,第二个是我们要传给Android的参数,query不是必须的,名字自己定,然后他会拼接到url后面的
- flutter中直接调用openPage
FlutterBoost.singleton.openPage("oa://createNew", {
"query": {"userid":"123"}
});
- android中:我们在application中进行了初始化,初始化的时候我们实现了一个startActivty的方法,我们就是通过这个方法来进行调整Activity的,在这里去判断应该调整哪个activity,我上面是按照官网来搬了一个统一路由跳转的类
public class PageRouter {
public static final String CREATE_NEW = "oa://createNew";
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(CREATE_NEW)){
context.startActivity(new Intent(context,CreateFunnyActivity.class));
return true;
} else {
return false;
}
} catch (Throwable t) {
return false;
}
}
}
- Android中嵌入Flutter界面,这里我们继承的就不是Activity而是BoostFlutterFragment了,使用方法和activity没什么区别,说到这里就顺带说一下一个原生界面中附带flutter和原生两种界面的问题了,我们就是直接把fragment弄成一个小区域就成了
public class FlutterPageFragment extends BoostFlutterFragment
- Flutter中嵌入Android的View
- 首先定义一个类实现PlatformView
package com.example.funny.flutter;
import android.content.Context;
import android.view.View;
import android.widget.TextView;
import java.util.Map;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.platform.PlatformView;
public class MyFlutterView implements PlatformView {
private TextView view;
public MyFlutterView(Context context, BinaryMessenger messenger, int id, Map<String, Object> map) {
TextView textView = new TextView(context);
textView.setText("这是AndroidView");
this.view = textView;//我们返回一个text
}
@Override
public View getView() {
return view;
}
@Override
public void dispose() {
}
}
- 建立一个工厂
public class MyFlutterFactory extends PlatformViewFactory {
private BinaryMessenger message;
public MyFlutterFactory(BinaryMessenger messenger) {
super(StandardMessageCodec.INSTANCE);
this.message = messenger;
}
@Override
public PlatformView create(Context context, int i, Object o) {
Map<String, Object> map = (Map<String, Object>) o;
return new MyFlutterView(context, message, i, map);
}
}
- 在我们的BoostFlutterActivity中注册一下这个View(以下截取了部分代码,就是我上面那个类)
public class FlutterPageActivity extends BoostFlutterActivity {
@Override
public void onRegisterPlugins(PluginRegistry registry) {
GeneratedPluginRegistrant.registerWith(registry);
final String key = FlutterPageActivity.class.getCanonicalName();
if (registry.hasPlugin(key)) return;
PluginRegistry.Registrar registrar = registry.registrarFor(key);
registrar.platformViewRegistry().registerViewFactory("plugins.nightfarmer.top/myTestView", new MyFlutterFactory(registrar.messenger()));
}
- Flutter中我们直接引用(这里我判断了设备是Android还是ios,如果是Android,我就加载Android的view,用AndroidView()这个方法,如果不是Android设备我就走flutter的)
child:Platform.isAndroid?AndroidView(viewType: 'plugins.nightfarmer.top/myTestView'):Text("这还是Flutter 的文字",style: TextStyle(color: Colors.white),)