鸿蒙-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 混编的介绍就已经结束了。

相关推荐
whysqwhw15 分钟前
鸿蒙Stack使用
harmonyos
whysqwhw36 分钟前
鸿蒙Flex使用
harmonyos
whysqwhw1 小时前
鸿蒙Row/Column使用
harmonyos
fouryears_234179 小时前
Flutter InheritedWidget 详解:从生命周期到数据流动的完整解析
开发语言·flutter·客户端·dart
zhanshuo13 小时前
在鸿蒙里优雅地处理网络错误:从 Demo 到实战案例
harmonyos
zhanshuo13 小时前
在鸿蒙中实现深色/浅色模式切换:从原理到可运行 Demo
harmonyos
LinXunFeng14 小时前
Flutter - 详情页 TabBar 与模块联动?秒了!
前端·flutter·开源
阅文作家助手开发团队_山神18 小时前
第三章: 解决Android iPad蓝牙键盘联想词UI不跟随光标问题
flutter
阅文作家助手开发团队_山神18 小时前
第四章:Flutter自定义Engine本地依赖与打包流程
前端·flutter
whysqwhw18 小时前
鸿蒙分布式投屏
harmonyos