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

相关推荐
武玄天宗34 分钟前
第四章、用flutter创建登录界面
flutter
搬砖的kk1 小时前
基于Flutter开发应用如何快速适配HarmonyOS
flutter·华为·harmonyos
码灵1 小时前
鸿蒙(HarmonyOS)开发板是否能够运行 Java 应用?
harmonyos
昼-枕1 小时前
Flutter深度解析:如何构建高性能、跨平台的移动应用
flutter
音浪豆豆_Rachel3 小时前
Flutter 与原生通信的桥梁:深入解析 Pigeon 与后台线程通信
flutter·harmonyos
音浪豆豆_Rachel3 小时前
Flutter跨平台通信的智能配置:Pigeon注解配置与鸿蒙生态深度集成
flutter·华为·harmonyos
Bryce李小白4 小时前
深入理解WidgetsFlutterBinding
flutter
开心_开心急了4 小时前
Ai加Flutter实现自定义标题栏(appBar)
前端·flutter
全栈派森5 小时前
Flutter 实战:基于 GetX + Obx 的企业级架构设计指南
前端·flutter