flutter_boost icon indicating copy to clipboard operation
flutter_boost copied to clipboard

调用BoostNavigator.instance.remove(pageInfo.uniqueId, arguments: ret)出现错误

Open joechan-cq opened this issue 3 years ago • 7 comments

Flutter Boost Version 3.0-null-safety-release.1 Target Platform: Android/iOS

FlutterA页面跳转到FlutterB页面,然后通过eventbus发送消息,让FlutterA页面关闭自身。使用的是下面的方法:

  /// 关闭当前的Flutter页面
  static void closeCurrentPage(BuildContext ctx, {Map<String, dynamic>? ret}) {
    PageInfo? pageInfo = BoostNavigator.instance.getPageInfoByContext(ctx);
    if (pageInfo != null) {
      BoostNavigator.instance.remove(pageInfo.uniqueId, arguments: ret);
    }
  }

然后报错,见日志

Logs

[  +14 ms] I/flutter ( 2933): Caught error: type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'Map<Object, Object>?' in type cast
[   +6 ms] I/flutter ( 2933): Caught stackTrace: #0      FlutterBoostAppState._removeContainer (package:flutter_boost/src/flutter_boost_app.dart:530:52)
[        ] I/flutter ( 2933): #1      FlutterBoostAppState.pop (package:flutter_boost/src/flutter_boost_app.dart:468:15)
[        ] I/flutter ( 2933): #2      FlutterBoostAppState.removeWithResult (package:flutter_boost/src/flutter_boost_app.dart:391:18)
[        ] I/flutter ( 2933): #3      BoostNavigator.remove (package:flutter_boost/src/boost_navigator.dart:107:17)

具体报错原因,_removeContainer内部对Map进行了强转(flutter_boost_app.dart):

  Future<void> _removeContainer(BoostContainer container) async {
    if (container.pageInfo.withContainer!) {
      Logger.log('_removeContainer ,  uniqueId=${container.pageInfo.uniqueId}');
      final params = CommonParams()
        ..pageName = container.pageInfo.pageName
        ..uniqueId = container.pageInfo.uniqueId
        ..arguments = container.pageInfo.arguments as Map<Object, Object>?;
      return await _nativeRouterApi!.popRoute(params);
    }
  }

而pageInfo的定义:

/// The PageInfo use in FlutterBoost ,it is not a public api
class PageInfo {
  PageInfo({this.pageName, this.uniqueId, this.arguments, this.withContainer});

  bool? withContainer;
  String? pageName;
  String? uniqueId;
  Map<String, dynamic>? arguments;
}

joechan-cq avatar May 19 '22 07:05 joechan-cq

popRoute为了回传结果,为什么用的是pageInfo中的arguments?不应该用外部业务层传进来的result么?就像正常pop中的代码

          final params = CommonParams()
            ..pageName = container!.pageInfo.pageName
            ..uniqueId = container.pageInfo.uniqueId
            ..arguments =
            (result is Map<String, dynamic>) ? result : <String, dynamic>{};
          await nativeRouterApi!.popRoute(params);

joechan-cq avatar May 19 '22 07:05 joechan-cq

@joechan-cq 呃,这里是传参到native侧,不是回传结果哈~

null-safaty这里的类型强转可能有些问题。

0xZOne avatar May 25 '22 09:05 0xZOne

@0xZOne 所以container != topContainer的情况下,是不能回传结果的? image

joechan-cq avatar May 25 '22 09:05 joechan-cq

@joechan-cq 有的,看这里:

image

0xZOne avatar May 25 '22 11:05 0xZOne

@0xZOne popWithResult方法是关闭顶层的Flutter容器页面吧。

我上面的没说清楚。Flutter A 跳转 Flutter B 再跳转 Flutter C,Flutter C页面某个功能会通知Flutter B关闭自身,并将某些数据回传给Flutter A。 在B中接收到通知后,使用下面的方法,关闭自身,并希望将ret回传给A。

    PageInfo? pageInfo = BoostNavigator.instance.getPageInfoByContext(ctx);
    if (pageInfo != null) {
      BoostNavigator.instance.remove(pageInfo.uniqueId, arguments: ret);
    }

但按照remove中的逻辑: image image image 会因为Flutter B并不是topContainer(Flutter C才是),因此进了if container != topContainer的逻辑,然后进入_removeContainer(container)后,直接return了,根本没有使用传进来的result参数。

joechan-cq avatar May 26 '22 01:05 joechan-cq

我上面的没说清楚。Flutter A 跳转 Flutter B 再跳转 Flutter C,Flutter C页面某个功能会通知Flutter B关闭自身,并将某些数据回传给Flutter A。 在B中接收到通知后,使用下面的方法,关闭自身,并希望将ret回传给A。

一开始确实没有考虑这种使用场景,如果有强诉求,可以考虑添加。欢迎提PR哈~

0xZOne avatar May 31 '22 10:05 0xZOne

@0xZOne 我看了下nativeRouterApi!.popRoute(params);的Native里的实现,Native中将params转化成FlutterBoostRouteOptions后,就交由delegate进行处理,delegate处理默认返回false,还是直接继续调用container.finishContainer方法,argument作为result传了进入。所以这个地方应该就是写错了,不应该用pageInfo的arguments。 image image

joechan-cq avatar Jun 01 '22 01:06 joechan-cq