本文主要内容是
一、flutter 与原生交互
主要记录,如何原生数据传递给flutter ,flutter数据传给原生app。
二、flutter路由跳转
flutter 页面跳转
一、flutter 与原生交互
第一步、Android studio 创建app ,项目名为TestFlutterEngine
创建flutter_moduel,在TestFlutterEngine文件上选择file->new flutter project,名称为test_engine_flutter_module
保持 TestFlutterEngine 与 test_engine_flutter_module在同一级目录
setting引入
//设置下面数据 TestFlutterEngine对应app名称 test_engine_flutter_module对应flutter module名称
setBinding(new Binding([gradle: this, mainModuleName: 'TestFlutterEngine']))
evaluate(new File(
settingsDir.parentFile,
'test_engine_flutter_module/.android/include_flutter.groovy'
))
build.gradle 引入flutter
implementation project(path: ':flutter')
现在,app与flutter进行关联了
第二步、想要app直接展示flutter 视图,需要初始化Engine 引擎,再绑定
FlutterFragment到activity布局里面
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initFlutterEngine()
//初始化flutter 页面
initFlutterFragment()
}
/**
* 初始化 Flutter Engine引擎
* Flutter Engine: 这是一个纯 C++实现的 SDK,其中囊括了 Skia引擎、Dart运行时、文字排版引擎等。
*/
private fun initFlutterEngine() {
mFlutterEngine = FlutterEngineCache.getInstance().get(engineId)
if (null == mFlutterEngine) {
mFlutterEngine = FlutterEngine(this)
mFlutterEngine!!.navigationChannel.setInitialRoute("/")
mFlutterEngine!!.dartExecutor.executeDartEntrypoint(
DartExecutor.DartEntrypoint.createDefault()
)
FlutterEngineCache
.getInstance()
.put(engineId, mFlutterEngine)
}
initMethodChannel()
}
/**
* 与flutter页面关联
*/
private fun initFlutterFragment() {
flutterFragment =
FlutterFragment.withCachedEngine(engineId)
.shouldAttachEngineToActivity(true)
.build() as FlutterFragment
supportFragmentManager
.beginTransaction()
.add(
R.id.fragment_container,
flutterFragment as Fragment,
"flutter_fragment"
).commit()
}
其中 R.id.fragment_container 对应的是xml中FragmentLayout控件
然后对Engine引擎的释放
override fun onDestroy() {
super.onDestroy()
releaseFlutterEngine()
}
/**
* 释放flutter引擎
*/
private fun releaseFlutterEngine() {
mFlutterEngine?.let { engine ->
FlutterEngineCache.getInstance().remove(engineId)
engine.destroy()
}
mFlutterEngine = null
}
第三步,建立通道,实现原生与flutter交互
/**
* 初始化channel 通道
* 可以有多个 通道
*/
private fun initMethodChannel(){
mMethodChannel = MethodChannel(mFlutterEngine!!.dartExecutor.binaryMessenger, channelName)
//设置监听Flutter回调原生方法
mMethodChannel?.setMethodCallHandler { call, result ->
Log.d(TAG,"call.method = " + call.method + " _argment ; " + call.arguments)
when (call.method) {
//原生传递数据给flutter
"sendDeviceId"->{
result.success("1234567890")
}
//获取flutter传过来的数据
"getToken"->{
val token = call.argument<String>("token")
Log.d(TAG, "token = $token")
}
//获取flutter传过来的数据 callHandler的使用, flutter等待回调使用
"update"->{
// val update = call.argument<String>("update")
val map = HashMap<String,String>()
map.put("words", "words")
map.put("imgPath","111111")
mMethodChannel?.invokeMethod("updateImage",map)
}
}
}
}
channelName 为通道名称,可以自己定义,也可以初始化多个通道
其中 setDeviceId 为原生传递给flutter ,通过result.success()传递过去
getToken 为flutter传递给原生数据 ,通过call.argument接收
update 实现 flutter传递给原生数据,原生通过mMethodChannel.invokeMethod 传递对象给flutter层,flutter实现callHandler 等待回调。 即可以理解为,flutter发起事件,原生app执行,原生app执行完回调给flutter,这时flutter 进行callhandler异步接收处理。
flutter 相关代码
getChannelMethodData() {
//获取原生传递数据
mc.callBack('sendDeviceId', '', (val) {
//获取原生传递的唯一设备号;
print('--->>>原生APP返回的设备号:$val <<<---');
}).catchError((error) {});
//主动发送数据给原生
mc.call('getToken', {'token': "我是一个token"});
}
Scaffold(
body: Center(
child: InkWell(
onTap: () {
mc.call('update', {'update': "callHandler"});
mc.callHandler("updateImage", (result) {
String words = result['words'];
String imgPath = result['imgPath'];
print("=========imgPath=" + imgPath + " words=" + words);
});
},
child: Container(
width: 200,
height: 100,
color: Colors.red,
child: Text(
'主动发起回调',
style: TextStyle(color: Colors.white, fontSize: 16),
),
),
)),
);
二、flutter路由跳转
我们知道 flutter 页面跳转都是依赖widget 跳转。我们可以看到flutter默认MaterialApp就可以设置
routes,进行widget页面管理。
接下来,我们实现功能从初始化页面跳转到APage,APage->BPage,BPage->CPage,CPage->DPage,然后下面2点功能
1、DPage 返回直接回到初始页面
2、DPage 返回回到APage,并保留初始页面,
相关代码
Scaffold(
body: Center(
child: InkWell(
onTap: () {
//移除 除A 其它的页面
// JumpPage.removeAllOutTargetPage(context, APage());
///重点:跳转到APage ,并移除除SplashPage外其它页面
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(builder: (context) => APage()),
ModalRoute.withName(SplashPage.routerName));
},
child: Text('DPage'),
)),
);
我们可以看到实现第二点功能相比Android实现更加简单