鸿蒙-flutter-使用FlutterEntry的路由管理和参数传递_下_页面返回时透传数据

前言

前面两篇介绍了如何打开指定页面,并且传递对应的参数。这一篇中我们来看下在页面返回时,如何将数据传递给上一个页面。

方案

按照之前的介绍,我们在flutter打开native时,也是通过methodChannel调用原生的方法打开的对应页面,那么当原生页面返回的时候,也是会将数据放在HMRouterPathCallback回调中返回。当我们获取到对应的数据之后,可以通过MethodResult将数据返回给flutter。 当flutter页面返回时,需要先判断能不能由flutter进行返回,不能返回的话再通过methodChannel调用 native返回。

实现

native页面返回

对于 native 页面返回,我们看一下上一篇中提到的 flutter 打开 native,在·EntryAbility·中调用的setRouterPushHandler,当页面返回的时候,会回调HMRouterMgr.push传入的HMRouterPathCallback对象中的方法。我们来改造一下setRouterPushHandler这个方法,将 MethodResult 对象也传过来,当页面返回的时候调用MethodResult.success将参数返回。

TypeScript 复制代码
FlutterRouterPlugin.setRouterPushHandler((path:string,args:Record<string,Object>|undefined,result: MethodResult)=>{
  console.error(`rouerHandler:path=> ${path} ,args=>${args}`)
  if(path =='pages/flutter/FromFlutterPage'){
    HMRouterMgr.push({pageUrl:'pages/flutter/FromFlutterPage',param:args},{
      onResult:(popInfo:PopInfo)=>{
        if(popInfo){
          result.success(popInfo.result)
        }else{
          result.success("")
        }
      }
    })
    return true
  }
  return false;
});

flutter页面返回

按照之前的介绍,flutter 返回也统一调用插件的返回方法。 在插件的FlutterRouterPlatform中添加pop方法:

dart 复制代码
void pop([args]) {
  throw UnimplementedError('open() has not been implemented.');
}

在插件的MethodChannelFlutterRouter中添加实现:

dart 复制代码
@override
void pop([args]) async {
  await methodChannel.invokeMethod('pop', args);
}

在插件的FlutterRouterPlugin中添加调用,这里我们还是将返回的处理交给宿主项目决定

TypeScript 复制代码
static routerPopHandler:(call:MethodCall,result: MethodResult)=>boolean =(call,result)=>{
  return false
}
static setRouterPopHandler(handler:(call:MethodCall,result: MethodResult)=>boolean){
  FlutterRouterPlugin.routerPopHandler = handler
}
onMethodCall(call: MethodCall, result: MethodResult): void {
  if(call.method =='pop'){
    FlutterRouterPlugin.routerPopHandler(call,result)
  }
}

在插件的FlutterRouter中统一调用返回的方法:先判断 flutter 是否可以 pop

dart 复制代码
void pop(context, [dynamic args]) {
  if (Navigator.of(context).canPop()) {
    Navigator.of(context).pop(args);
  } else {
    FlutterRouterPlatform.instance.pop(args);
  }
}

为了测试简单全面,我们在 flutter_module中添加一个 flutter 页面。

dart 复制代码
//from_flutter_page.dart

import 'package:flutter/material.dart';
import 'package:flutter_router/flutter_router.dart';
class FromFlutterPage extends StatefulWidget {
  final Map<String, dynamic> args;
  const FromFlutterPage(this.args,{  super.key});

  @override
  State<FromFlutterPage> createState() => _FromFlutterPageState();
}

class _FromFlutterPageState extends State<FromFlutterPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(centerTitle: true,title: Text('from flutter',style: TextStyle(fontSize: 16,color: Color(0xff333333)),),),
      body: Column(
        children: [
            Text("收到上个页面传过来的数据"),
          Text("${widget.args}"),
          ElevatedButton(
            onPressed: () {
              FlutterRouter().pop(context,{"user_id":"xuan","page_name":"FromFlutterPage"});
            },
            child: const Text("带数据返回上个页面",
                style: TextStyle(fontSize: 16, color: Color(0xff333333))),
          ),
        ],
      ),
    );
  }
}

注意,添加的页面需要在 flutter 侧注册一下

dart 复制代码
//main.dart
void initRouter(){
  RouterManager.instance.addRouter("login",(args){return LoginPage(args);});
  RouterManager.instance.addRouter("from_flutter",(args){return FromFlutterPage(args);});
}

之后我们在LoginPage中添加一下相关跳转、返回、参数展示

dart 复制代码
//login_page.dart
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter_router/flutter_router.dart';

class LoginPage extends StatefulWidget {
  final Map<String, dynamic> args;

  const LoginPage(this.args, {super.key});

  @override
  State<LoginPage> createState() => _LoginPageState();
}

class _LoginPageState extends State<LoginPage> {
  String nativeResult = "";
  String flutterResult = "";

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("登录页面"),
        centerTitle: true,
      ),
      body: Column(
        children: [
          const Text("登录页面获取到的参数",
              style: TextStyle(fontSize: 16, color: Color(0xff333333))),
          Text(jsonEncode(widget.args)),
          Text("name:${widget.args['name']}"),
          Text("age:${widget.args['age']}"),
          ElevatedButton(
            onPressed: () {
              //HMRouterAPage
              FlutterRouter().open(context, 'pages/flutter/FromFlutterPage',
                  arguments: {
                    'name': 'flutter_harmony',
                    'age': 3
                  }).then((value) {
                debugPrint("native页面返回 flutter 传递的参数 ${jsonEncode(value)}");
                setState(() {
                  nativeResult = jsonEncode(value);
                });
              });
            },
            child: const Text("FromFlutterPage",
                style: TextStyle(fontSize: 16, color: Color(0xff333333))),
          ),
          ElevatedButton(
            onPressed: () {
              FlutterRouter().open(context, "from_flutter", arguments: {
                "from": "LoginPage",
                "business_id": "123"
              }).then((value) {
                debugPrint("flutter页面返回 flutter 传递的参数 ${jsonEncode(value)}");
                setState(() {
                  flutterResult = jsonEncode(value);
                });
              });
            },
            child: const Text("跳转到 flutter",
                style: TextStyle(fontSize: 16, color: Color(0xff333333))),
          ),
          ElevatedButton(
            onPressed: () {
              FlutterRouter().pop(context, {"user_id": "xuan"});
            },
            child: const Text("返回上个页面携带参数",
                style: TextStyle(fontSize: 16, color: Color(0xff333333))),
          ),
          Container(
            margin: const EdgeInsets.all(15),
            color: const Color(0xff9c649a),
            child: Column(
              children: [const Text('flutter页面返回携带的参数:'), Text(flutterResult)],
            ),
          ),
          Container(
            margin: const EdgeInsets.all(15),
            color: const Color(0xff7b7a32),
            child: Column(
              children: [const Text('native页面返回携带的参数:'), Text(nativeResult)],
            ),
          ),
        ],
      ),
    );
  }
}

这样我们在 flutter 中需要做的事情就已经做完了,执行flutter build har --debug会在my_flutter_module/.ohos/har文件夹下看到三个har文件,直接复制到鸿蒙工程中进行依赖就行了。记得把源码依赖删掉

json 复制代码
//oh-package.json5
{
  "modelVersion": "5.0.5",
  "description": "Please describe the basic information.",
  "dependencies": {
    "@hadss/hmrouter": "1.0.0-rc.10",
    "@ohos/flutter_ohos": "file:./har/flutter.har",
    "@ohos/flutter_module": ".//har/flutter_module.har",
    "flutter_router": "file:./har/flutter_router.har"
  }
  "overrides": {
    "@ohos/flutter_ohos": "file:./har/flutter.har",
    "flutter_router": "file:./har/flutter_router.har"
  }
}

最后一步,在EntryAbility中设置一下处理返回的调用

TypeScript 复制代码
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
  FlutterRouterPlugin.setRouterPopHandler((call:MethodCall,result: MethodResult)=>{
    console.error(`flutter 调用 pop  setRouterPopHandler:  ${call.method}  ${call.args}`)
    HMRouterMgr.pop({param:call.args})
    return true;
  })
}

这样我们就完成了页面返回时参数的传递。

结论

先看下效果

总结一下:

  1. native 打开 flutter 时,将参数拼接到初始化路径上。
  2. flutter 侧需要将所有的页面注册到插件中
  3. flutter 打开页面时,插件判断目标页面是 flutter 还是 native,选择对应的方法打开页面
  4. 页面返回时,通过 MethodResult 将数据返回

至此,鸿蒙和 flutter 混编的介绍就已经结束了。

相关推荐
颜颜颜yan_2 小时前
【HarmonyOS5】掌握UIAbility启动模式:Singleton、Specified、Multiton
后端·架构·harmonyos
二蛋和他的大花3 小时前
HarmonyOS运动开发:深度解析文件预览的正确姿势
华为·harmonyos
无知的前端3 小时前
Flutter开发,GetX框架路由相关详细示例
android·flutter·ios
长弓三石4 小时前
鸿蒙网络编程系列53-仓颉版TCP连接超时分析示例
前端·harmonyos
libo_20254 小时前
DevEco Studio测试用例录制功能详解(HarmonyOS 5)
harmonyos
lewis_dys4 小时前
微信内引导用户使用“在浏览器打开”开发参考
harmonyos
zhanshuo5 小时前
告别卡顿!鸿蒙新闻列表流畅滚动优化全攻略
harmonyos
zhanshuo5 小时前
鸿蒙开发者必看!三步搞定动态权限请求,告别用户权限流失
harmonyos
王二蛋与他的张大花5 小时前
HarmonyOS运动开发:深度解析文件预览的正确姿势
harmonyos
TRockBots6 小时前
三、DevEco Studio安装和HelloWorld应用
harmonyos