Flutter路由管理插件navigator_manager的使用

Flutter路由管理插件navigator_manager的使用

简介

navigator_manager 是一个基于 Flutter 2.0 的导航器插件,适用于应用程序和网页。它提供了许多有用的方法,可以轻松地传递参数。

快速开始

main.dart 文件中引入路由管理,并进行路由配置。

初始化路由管理

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  [@override](/user/override)
  State<StatefulWidget> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final _routerDelegate = LRouterDelegate(
    // 配置没有匹配URL的页面(app可不配置)
    pageNotFound: (uri, params) => MaterialPage(
      key: ValueKey('not-found-page'),
      child: Builder(
        builder: (context) => Scaffold(
          body: Center(
            child: Text('Page ${uri.path} not found'),
          ),
        ),
      ),
    ),
    // 配置所有路由信息(必填)
    routes: {
      '/': (uri, params) => CreateRoutePage(name: 'main', child: HomePage()),
      '/test/todo': (uri, params) => CreateRoutePage(name: 'test', child: TestPage(uri)),
      '/result': (uri, params) => CreateRoutePage(name: 'result', child: ResultPage()),
      '/login': (uri, params) => CreateRoutePage(name: 'login', child: LoginPage()),
    },
  );

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp.router(
      title: 'Uri navigator App',
      routerDelegate: _routerDelegate,
      routeInformationParser: LRouteInformationParser(),
    );
  }
}

方法

  1. go(Uri uri, {dynamic params})

    • 路由跳转方法, 支持路由传参和自定义数据类型传参
    RouteManager.go(Uri(path: '/test/todo', queryParameters: {'limit': '12'}));
    RouteManager.go(Uri(path: '/test/todo'), params: yourModel);
    
  2. replace(Uri uri, {dynamic params})

    • 替换当前路由并跳转
    RouteManager.replace(Uri(path: '/test/todo'));
    
  3. goBack()

    • 返回上一页, 如若返回传参请用 returnResultGo
    RouteManager.goBack();
    
  4. clearAndGo(Uri uri, {dynamic params})

    • 清空路由栈并重设首页,如登陆场景
    RouteManager.clearAndGo(Uri(path: '/login'));
    
  5. multipleGo(List<Uri> uris, {List<dynamic> params})

    • 一次设置多个uri并跳转到最后一个路由
    RouteManager.multipleGo([Uri(path: '/test/todo', queryParameters: {'limit': '12'}), Uri(path: '/test/todo')]);
    
  6. clearAndMultipleGo(List<Uri> uris, {List<dynamic> params})

    • 清空路由栈并跳转(设置多个uri)
    RouteManager.clearAndMultipleGo(Uri(path: '/test/todo', queryParameters: {'limit': '12'}));
    
  7. waitResultGo(Uri uri, {dynamic params})

    • 跳转等待结果
    RouteManager.waitResultGo(Uri(path: '/test/todo', queryParameters: {'limit': '12'}));
    
  8. returnResultGo(dynamic value)

    • 跳转返回结果
    RouteManager.returnResultGo(yourValue);
    
  9. goRoot()

    • 路由栈只保留首页
    RouteManager.goRoot();
    
  10. removeUri(Uri uri)

    • 删除指定路由
    RouteManager.removeUri(Uri(path: '/test/todo'));
    
  11. removeLastUri()

    • 删除栈顶的路由
    RouteManager.removeLastUri();
    

页面监听

路由栈变化的监听有两种方式:

routerDelegate.addListener(() {
  if (routerDelegate.currentConfiguration == Uri(path: '/')) {
    /// to do
  }
}
class APage extends StatefulWidget {
  const APage({Key key}) : super(key: key);

  [@override](/user/override)
  _APageState createState() => _APageState();
}

// 3. Add `with RouteAware, RouteObserverMixin` to State and override RouteAware methods.
class _APageState extends State<APage> with RouteAware, RouteObserverMixin {

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Text('A Page'),
      ),
    );
  }

  /// Called when the top route has been popped off, and the current route
  /// shows up.
  [@override](/user/override)
  void didPopNext() { }

  /// Called when the current route has been pushed.
  [@override](/user/override)
  void didPush() { }

  /// Called when the current route has been popped off.
  [@override](/user/override)
  void didPop() { }

  /// Called when a new route has been pushed, and the current route is no
  /// longer visible.
  [@override](/user/override)
  void didPushNext() { }
}

示例代码

以下是完整的示例代码:

import 'package:navigator_manager/navigator_manager.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  [@override](/user/override)
  State<StatefulWidget> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final _routerDelegate = LRouterDelegate(
    // 配置web用的路由没有匹配的页面 app正常情况下无需
    pageNotFound: (uri, params) => MaterialPage(
      key: ValueKey('not-found-page'),
      child: Builder(
        builder: (context) => Scaffold(
          body: Center(
            child: Text('Page ${uri.path} not found'),
          ),
        ),
      ),
    ),
    // 配置所有路由信息
    routes: {
      '/': (_, __) => CreateRoutePage(name: 'home', child: Home()),
      '/test/todo': (uri, _) => CreateRoutePage(
        name: 'test', 
        child: Test(uri: uri, text: uri.queryParameters['text'],), 
        transition: (animation, child) => ScaleTransition(
          alignment: Alignment.bottomLeft,
          scale: Tween(
            begin: 0.0,
            end: 1.0,
          ).animate(
            CurvedAnimation(
              parent: animation,
              curve: Curves.easeInOut,
            ),
          ),
          child: child,
        )
      ),
      '/result': (_, __) => CreateRoutePage(name: 'result', child: Result()),
      '/login': (_, params) => CreateRoutePage(name: 'login', child: Login(params)),
    },
  );

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp.router(
      title: 'Uri navigator App',
      routerDelegate: _routerDelegate,
      routeInformationParser: LRouteInformationParser(),
    );
  }
}

class Home extends StatelessWidget {
  const Home({Key? key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Home Page'),
        automaticallyImplyLeading: true,
      ),
      body: Center(
        child: Column(
          children: [
            TextButton(
              onPressed: () {
                // 跳转
                RouteManager.go(
                    Uri(path: '/test/todo', queryParameters: {'text': '12'}));
              },
              child: Text('Test go'),
            ),
            TextButton(
              onPressed: () {
                // 跳转无匹配路由
                RouteManager.go(Uri(path: '/test/haha'));
              },
              child: Text('Test not found'),
            ),
            TextButton(
              onPressed: () {
                // 清除路由栈并跳转
                RouteManager.clearAndGo(Uri(path: '/login'), params: UserInfo(name: 'your name', age: 18));
              },
              child: Text('Test clearAndGo'),
            ),
            TextButton(
              onPressed: () {
                // 清除路由栈并跳转(设置多个路由)
                RouteManager.clearAndMultipleGo([Uri(path: '/test/todo', queryParameters: {'text': '12'}), Uri(path: '/test/todo')]);
              },
              child: Text('clearAndMultipleGo'),
            ),
            TextButton(
              onPressed: () async{
                // 等待结果跳转 配合returnResultGo使用
                final result = await RouteManager.waitResultGo(Uri(path: '/result'));
                print(result);
              },
              child: Text('waitResultGo'),
            ),
          ],
        ),
      ),
    );
  }
}

class Test extends StatefulWidget {
  final uri;
  final text;
  Test({
    this.uri,
    this.text, 
    Key? key,
  }) : super(key: key);

  [@override](/user/override)
  _TestState createState() => _TestState();
}

class _TestState extends State<Test> with RouteAware, RouteObserverMixin {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Test Page'),
        automaticallyImplyLeading: true,
      ),
      body: Center(
        child: Column(
          children: [
            Text('test ${widget.uri}'),
            Text('text = ${widget.text}'),
            TextButton(
              onPressed: () {
                // 返回
                RouteManager.goBack();
              },
              child: Text('Back'),
            ),
            TextButton(
              onPressed: () {
                // 返回
                RouteManager.go(
                    Uri(path: '/test/todo', queryParameters: {'text': '10'}));
              },
              child: Text('goText'),
            ),
          ],
        ),
      ),
    );
  }

  /// Called when the top route has been popped off, and the current route
  /// shows up.
  [@override](/user/override)
  void didPopNext() {
    print('didpopnext');
  }

  /// Called when the current route has been pushed.
  [@override](/user/override)
  void didPush() {
    print('didpush');
  }

  /// Called when the current route has been popped off.
  [@override](/user/override)
  void didPop() {
    print('didpop');
  }

  /// Called when a new route has been pushed, and the current route is no
  /// longer visible.
  [@override](/user/override)
  void didPushNext() {
    print('didpushnext');
  }
}

class Result extends StatelessWidget {
  const Result({Key? key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Result Page'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            TextButton(
              // 返回结果
              onPressed: () => RouteManager.returnResultGo({'uid': 1}),
              child: Text('只有调用returnResultGo才带有参数, 默认返回不带参数'),
            ),
          ],
        ),
      ),
    );
  }
}

class UserInfo {
  final String? name;
  final int? age;
  UserInfo({this.name, this.age});
}

class Login extends StatelessWidget {
  final UserInfo userInfo;
  const Login(this.userInfo, {Key? key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Login Page'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('${userInfo.name}'),
            Text('${userInfo.age}'),
            TextButton(
              // 返回结果
              onPressed: () => RouteManager.go(Uri(path: '/login'), params: UserInfo(name: 'your name', age: 20)),
              child: Text('登陆'),
            ),
          ],
        ),
      ),
    );
  }
}

更多关于Flutter路由管理插件navigator_manager的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter路由管理插件navigator_manager的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,navigator_manager 是一个用于 Flutter 应用中管理路由的插件,它能够帮助开发者更方便地管理页面跳转和导航。以下是一个简单的示例,展示如何使用 navigator_manager 进行路由管理。

首先,确保你已经在 pubspec.yaml 文件中添加了 navigator_manager 依赖:

dependencies:
  flutter:
    sdk: flutter
  navigator_manager: ^x.y.z  # 请替换为最新版本号

然后,运行 flutter pub get 来获取依赖。

接下来,我们将配置 navigator_manager 并进行路由管理。

1. 初始化 NavigatorManager

在你的主应用文件(通常是 main.dart)中,初始化 NavigatorManager 并设置初始路由。

import 'package:flutter/material.dart';
import 'package:navigator_manager/navigator_manager.dart';

void main() {
  // 初始化 NavigatorManager
  NavigatorManager.init(
    MaterialApp(
      home: NavigatorManager.defaultRoute(),  // 设置初始路由
      routes: {
        '/home': (context) => HomeScreen(),
        '/details': (context) => DetailsScreen(),
      },
    ),
  );
}

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Home')),
      body: Center(
        child: ElevatedButton(
          onPressed: () => NavigatorManager.pushNamed('/details'),
          child: Text('Go to Details'),
        ),
      ),
    );
  }
}

class DetailsScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Details')),
      body: Center(
        child: ElevatedButton(
          onPressed: () => NavigatorManager.pop(),
          child: Text('Go Back'),
        ),
      ),
    );
  }
}

2. 使用 NavigatorManager 进行路由跳转

在上述代码中,我们已经在 HomeScreen 中使用 NavigatorManager.pushNamed('/details') 进行了路由跳转,并在 DetailsScreen 中使用 NavigatorManager.pop() 返回上一个页面。

3. 配置默认路由(可选)

你还可以配置一个默认路由,当没有指定路由时显示该路由。这通常在 NavigatorManager.init 时设置:

NavigatorManager.init(
  MaterialApp(
    home: NavigatorManager.defaultRoute(
      '/home',  // 设置默认路由为 '/home'
      (context) => HomeScreen(),
    ),
    routes: {
      '/home': (context) => HomeScreen(),
      '/details': (context) => DetailsScreen(),
    },
  ),
);

4. 动态添加路由(可选)

你也可以在运行时动态添加路由。这在某些复杂的应用中可能会用到。

NavigatorManager.addRoute('/newScreen', (context) => NewScreen());

然后在需要的时候进行跳转:

NavigatorManager.pushNamed('/newScreen');

完整示例

以下是一个完整的示例,展示了如何初始化 NavigatorManager、设置路由并进行跳转:

import 'package:flutter/material.dart';
import 'package:navigator_manager/navigator_manager.dart';

void main() {
  NavigatorManager.init(
    MaterialApp(
      home: NavigatorManager.defaultRoute(
        '/home',
        (context) => HomeScreen(),
      ),
      routes: {
        '/home': (context) => HomeScreen(),
        '/details': (context) => DetailsScreen(),
      },
    ),
  );
}

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Home')),
      body: Center(
        child: ElevatedButton(
          onPressed: () => NavigatorManager.pushNamed('/details'),
          child: Text('Go to Details'),
        ),
      ),
    );
  }
}

class DetailsScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Details')),
      body: Center(
        child: ElevatedButton(
          onPressed: () => NavigatorManager.pop(),
          child: Text('Go Back'),
        ),
      ),
    );
  }
}

以上代码展示了如何使用 navigator_manager 插件进行基本的路由管理。根据具体需求,你可以进一步自定义和扩展这些功能。

回到顶部