您的当前位置:首页正文

Flutter路由跳转参数处理技巧详解

2024-11-11 来源:个人技术集锦

需求

我们在开发应用中,经常会出现一个界面跳转到另外一个界面并带有参数传递,在Android中大家都知道使用Intent传递参数,在第二个Activity中onCreate中可以获取到这个参数。

实现

那么在Flutter中,我们经常会使用路由跳转到另外一个界面,那么如果这个时候需要传参。

代码如下:

/// 路由跳转并带参数
 Navigator.pushNamed(
            context,
            RouteConst.routeNext,
            arguments: (TestArguments("一笑轮回", "江苏省徐州市")),
);       
/// 测试数据模型
class TestArguments {
  String? name;
  String? address;
  TestArguments(this.name, this.address);
}

赋值arguments字段

没错,直接赋值arguments字段就可以了,那么我们如何获取呢?

在第二个页面中

class TwoPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // 从路由设置中获取传递的参数
    var arguments = ModalRoute.of(context)?.settings.arguments;
    // 其他部分的代码...
  }
}

我们需要通过 ModalRoute.of(context)?.settings.arguments获取数据,那么我们直接在 initState方法中直接通过 ModalRoute.of(context)?.settings.arguments获取,会报错

这里出错原因,可以通过错误并查看源码可知,这里部讲述。

我们有的时候需要在initState方法中获取数据并处理一些事情,我们应该怎么做呢?

下面提供一个小技巧。

路由定义

class RouteConst {
  static const routeNext = "/route_next";
}
class RoutePathConst {
  static var routePaths = <String, Widget Function(BuildContext context)>{
    RouteConst.routeNext: (context) => ArgumentsNextPage(),
  };
}

跳转代码

Navigator.pushNamed(
            context,
            RouteConst.routeNext,
            arguments: (TestArguments("一笑轮回", "江苏省徐州市")),
          );
/// 测试数据模型
class TestArguments {
  String? name;
  String? address;
  TestArguments(this.name, this.address);
}

定义ArgumentsMixin

/// Arguments参数数据
mixin ArgumentsMixin {
  late final Object? arguments;
}
/// 路由拼接的参数数据
mixin RouteQueryMixin {
  final Map<String, String> routeParams = HashMap();
}

重写onGenerateRoute

void main() {
  runApp(const MyApp());
}
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      ...
      onGenerateRoute: (settings) {
        var uri = Uri.parse(settings.name ?? "");
        var route = uri.path;
        var params = uri.queryParameters;
        if (!RoutePathConst.routePaths.containsKey(route)) {
          return null;
        }
        return MaterialPageRoute(
          builder: (context) {
            var widgetBuilder = RoutePathConst.routePaths[route];
            var widget = widgetBuilder!(context);
            if (widget is RouteQueryMixin) {
              (widget as RouteQueryMixin).routeParams.addAll(params);
            }
            if (widget is ArgumentsMixin) {
              (widget as ArgumentsMixin).arguments = settings.arguments;
            }
            return widget;
          },
          settings: settings,
        );
      },
    );
  }
}

创建ArgumentsNextPage

///第二页
class ArgumentsNextPage extends StatefulWidget
    with ArgumentsMixin, RouteQueryMixin {
  ArgumentsNextPage({super.key});
  @override
  State<ArgumentsNextPage> createState() => _ArgumentsNextPageState();
}
class _ArgumentsNextPageState extends State<ArgumentsNextPage> {
  /// 传参数据文本
  String get result {
    // Arguments传参数据
    TestArguments? arguments;
    if (widget.arguments != null && widget.arguments is TestArguments) {
      arguments = widget.arguments as TestArguments;
    }
    // 路由拼接的数据
    var params = widget.routeParams;
    // 拼接结果数据
    return "arguments:name=${arguments?.name ?? ""} address=${arguments?.address ?? ""} \nrouteParams=$params";
  }
  @override
  void initState() {
    super.initState();
    print("result=$result}");
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: XYAppBar(
        title: "第二页",
        onBack: () {
          Navigator.pop(context);
        },
      ),
      body: Center(
        child: Text(result),
      ),
    );
  }
}

这样就OK了,好像没讲啥,直接看代码吧。

详细代码见:

Top