关于flutter:flutter系列之Navigator的高级用法

32次阅读

共计 3516 个字符,预计需要花费 9 分钟才能阅读完成。

简介

上篇文章咱们讲到了 flutter 中 navigator 的根本用法,咱们能够应用它的 push 和 pop 办法来进行 Router 之间的跳转。

在 flutter 中一个 Router 就是一个 widget,然而在 Android 中,一个 Router 就是 Activity, 在 IOS 中,一个 Router 是一个 ViewController。

Router 除了之前讲过的 push 和 pop 办法之外,还有一些更加高级的用法,一起来看看吧。

named routes

尽管在 flutter 中 navigator 将 routers 以 stack 的模式进行存储,能做的也只是 push 和 pop 操作,然而事实上 Router 是能够有名字的。

想想也是,如果 Router 没有名字的话,那么如何顺利进行跳转呢?不可能每次都 new 一个 Router 进去吧。

navigator 有一个办法叫做 Navigator.pushNamed() 用来将带名字的 Router 压入堆栈,咱们来看下它的定义:

  static Future<T?> pushNamed<T extends Object?>(
    BuildContext context,
    String routeName, {Object? arguments,}) {return Navigator.of(context).pushNamed<T>(routeName, arguments: arguments);
  }

这个办法须要传入一个 context 和对应的 routeName,同时还能够带一些参数。

那么怎么用这个办法呢?

首先咱们须要定义一些 Router,比如说在创立 MaterialApp 的时候能够传入 routes 参数,来设置 named Routers:

MaterialApp(
  title: '这是 named Routers',
  initialRoute: '/firstPage',
  routes: {'/firstPage': (context) => const FirstPage(),
    '/secondPage': (context) => const SecondPage(),},
)

下面的代码中咱们别离定了两个 routers,别离是 firstPage 和 secondPage, 他们别离对应一个自定义的 widget。

定义好 Router 之后,咱们就能够向上面这样应用了:

onPressed: () {Navigator.pushNamed(context, '/secondPage');
}

如果要返回第一个页面的话,那么能够调用 Navigator.pop 办法来实现:

onPressed: () {Navigator.pop(context);
}

给 named route 传参数

在上一节咱们讲到 pushNamed 的时候,还介绍了它还能够接管参数 arguments。从定义上能够看到 arguments 的类型是 Object 对象,也就是说任何对象都能够作为 named route 的参数。

那么咱们先定义一个对象如下:

class TestArguments {
  final String name;
  final String description;

  TestArguments(this.name, this.description);
}

接下来咱们须要创立一个可能承受这个参数的 Routers。

因为所有的 Routers 都是 Widget,所以咱们须要创立一个 Widget, 并在这个 widget 外部接管传入的参数。

在 flutter 中有两种传递参数的形式,你能够应用 ModalRoute.of(),也能够应用 onGenerateRoute()。

咱们先来看下 ModalRoute.of 的定义:

  static ModalRoute<T>? of<T extends Object?>(BuildContext context) {final _ModalScopeStatus? widget = context.dependOnInheritedWidgetOfExactType<_ModalScopeStatus>();
    return widget?.route as ModalRoute<T>?;
  }

它接管一个 context 参数,而后返回一个 route 对象。

具体的用法如下:

class FirstPage extends StatelessWidget {const FirstPage({super.key});

  static const routeName = '/firstPage';

  @override
  Widget build(BuildContext context) {final args = ModalRoute.of(context)!.settings.arguments as TestArguments;

    return Scaffold(
      appBar: AppBar(title: Text(args.name),
      ),
      body: Center(child: Text(args.description),
      ),
    );
  }
}

除了应用 ModalRoute 之外,还能够在 onGenerateRoute() 办法中进行参数传递。onGenerateRoute 是在 Route 生成的时候触发的:

MaterialApp(onGenerateRoute: (settings) {if (settings.name == FirstPage.routeName) {
 
      final args = settings.arguments as TestArguments;

      return MaterialPageRoute(builder: (context) {
          return TestArguments(
            title: args.title,
            message: args.message,
          );
        },
      );
    }
    return null;
  },
)

onGenerateRoute 接管一个 settings 对象,咱们须要在 settings 对象中设置对应的 name 和 arguments 属性。所以咱们须要这样调用:

    Navigator.pushNamed(
      context,
      FirstPage.routeName,
      arguments: TestArguments(
        '测试',
        '这是一个 named Route',
      ),
    );

从 Screen 返回值

有时候咱们须要从一个 Screen 返回到之前的 Screen,并且不是简略的返回,咱们还心愿晓得前一个 screen 返回了什么后果,而后能够依据前一个 screen 返回的不同后果来进行不同的解决。

这个时候就须要用到 Navigator.pop 的传参性能了。

比方咱们在第一个页面中点击了按钮,跳转到第二个页面:

  final result = await Navigator.push(
      context,
      MaterialPageRoute(builder: (context) => const SecondScreen()),
    );

这里咱们应用到了 Navigator.push 办法,并且返回了一个 result 的值。

咱们能够应用这个值来进行一些逻辑判断。

那么这个 result 的值是哪里传递过去的呢?

没错,就是 SecondScreen 中的 Navigator.pop 办法:

Navigator.pop(context, 'Yes');

这里的 ’Yes’ 就会传递给 result 供咱们进行逻辑判断。

向 Screen 传值

有时候咱们须要在页面跳转的过程中传递一些参数,那么怎么能力实现 Screen 之间的参数传递呢?

因为在 flutter 中所有的 Routers 都是 Widget,所以咱们能够在跳转到新的页面的时候间接将参数以构造函数的形式传递给 Routers Widget。

比方咱们有上面的 Screen Widget:

class NameScreen extends StatelessWidget {const NameScreen({super.key, required this.name});

  final String name;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('NameScreen'),
      ),

      body: 
      ...
      ;
  }
}

想要传值给它,能够在 onTap 办法中这样写:

onTap: () {
        Navigator.push(
          context,
          MaterialPageRoute(builder: (context) => NameScreen(name: 'what is your name?'),
          ),
        );

总结

以上就是 Navigator 的更加高级的用法,咱们能够通过 Navigator 来进行数据传递等操作,从而实现更加简单的页面性能。

正文完
 0