Flutter路由管理插件r_router的使用

Flutter路由管理插件r_router的使用

r_router

pub package

r_router是一个Flutter路由包,你可以不使用context来导航,支持对话框/路径正则表达式/自定义导航过渡/Navigator 2.0。

中文介绍

中文介绍请参见这里

开始使用

1. 引入插件

pubspec.yaml文件中添加以下代码:

dependencies:
  r_router: last version
2. 导入包

在你的Dart文件中添加以下导入语句:

import 'package:r_router/r_router.dart';

简单使用

注册路由
/// [path] 你的路由路径。
/// [handler] 处理Widget ((ctx) => PageOne()))
/// [PageOne] 你的页面。
/// [ctx] 请求数据。
RRouter.addRoute(NavigatorRoute('/one', (ctx) => PageOne()));
在应用中添加路由(Navigator 1.0)
class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      // 添加新的观察者
      navigatorObservers: [
        RRouter.observer,
      ],
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}
在应用中添加路由(Navigator 2.0)
class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp.router(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      routerDelegate: RRouter.delegate,
      routeInformationParser: RRouter.informationParser,
    );
  }
}
导航到该页面
/// [path] 你注册的路径。
/// [body] 你想给[path]传递的参数。
/// [replace] 是否替换当前路由。
/// [clearTrace] 是否清除所有路由并推送到[path]。
/// [isSingleTop] 如果[path]已经是顶部,则无响应。
/// [pageTransitions] 你导航时的过渡动画,如果为null则使用默认的Page Transitions Builder。
RRouter.navigateTo('/one');

注册路由

/// 设置错误页面。
RRouter.setErrorPage(ErrorPageWrapper(
    error: (BuildContext context, FlutterErrorDetails flutterErrorDetails) =>
        Center(
          child: Text(
            '异常页面 (${flutterErrorDetails.exceptionAsString()})',
          ),
        ),
    notFound: (BuildContext context, Context ctx) => Material(
          child: Center(
            child: Text('页面未找到:${ctx.path}'),
          ),
        )));

/// 设置页面构建转换,默认为平台页面过渡。
RRouter.addRoute(NavigatorRoute('/three', (ctx) => PageThree(),
    defaultPageTransaction: CupertinoPageTransitionsBuilder()))

不使用context显示对话框

支持以下方法:

  • RRouter.showDialog
  • RRouter.showCupertinoDialog
  • RRouter.showCupertinoModalPopup
  • RRouter.showAboutDialog
  • RRouter.showMenu
  • RRouter.showTimePicker
  • RRouter.showGeneralDialog
  • RRouter.showDatePicker
  • RRouter.showDateRangePicker
  • RRouter.showSearch
  • RRouter.showModalBottomSheet
  • RRouter.showLicensePage

默认Navigator

你可以使用

RRouter.navigator

添加拦截器

RRouter.addInterceptor((ctx) async {
  if (ctx.path == '/other') {
    RRouter.navigateTo('/five', body: ctx.body);
    return true;
  }
  return false;
});

使用/user/:id或/user/*注册路由路径

RRouter.addRoute(NavigatorRoute('/five/:id', (ctx) => PageFive(id:ctx.pathParams.getInt('id'))));
RRouter.addRoute(NavigatorRoute('/five/*', (ctx) => PageFive()));

从BuildContext获取ctx

Context ctx = context.readCtx;

重定向

RRouter.addRoute(NavigatorRoute('/showDialog', (ctx) async {
      return null;
    }, responseProcessor: (c, p) async {
      await showRDialog(
          routeSettings: RouteSettings(name: c.path, arguments: c.body),
          builder: (context) => AlertDialog(
                title: Text('标题'),
                content: Text('内容'),
                actions: [
                  TextButton(
                      onPressed: () {
                        Navigator.pop(context);
                      },
                      child: Text('确定')),
                ],
              ));
      return c.isDirectly == true ? Redirect(path: '/') : null;
    }));

// 或者
RRouter.addRoute(NavigatorRoute('/showDialog', (ctx) async {
      return Redirect(path: '/');
    }));

返回首页事件

RRouter.setPopHome(() {
  return Future.value(true); // 如果为true将保持,否则将返回首页
})

完整示例Demo

import 'package:flutter/material.dart';
import 'package:r_router/r_router.dart';
import 'package:example/src/page/page_five.dart';
import 'package:example/src/page/page_four.dart';
import 'src/page/my_page.dart';
import 'src/page/page_one.dart';
import 'src/page/page_three.dart';
import 'src/page/page_two.dart';

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

void initRouter() {
  // 初始化设置
  RRouter.setPathStrategy(true)
      .setErrorPage(ErrorPageWrapper(
          error: (BuildContext context,
                  FlutterErrorDetails flutterErrorDetails) =>
              Center(
                child: Text(
                  '异常页面 (${flutterErrorDetails.exceptionAsString()})',
                ),
              ),
          notFound: (BuildContext context, Context ctx) => Material(
                child: Center(
                  child: Text('页面未找到:${ctx.path}'),
                ),
              )))
      .addRoute(NavigatorRoute(
          '/',
          (ctx) => MyHomePage(
                title: '我的主页',
              )))
      .addRoute(NavigatorRoute('/one', (ctx) => PageOne()))
      .addRoute(NavigatorRoute(
          '/two',
          (ctx) => PageTwo(
                param: ctx.body != null ? ctx.body['param'] : '',
              )))
      .addRoute(NavigatorRoute('/three', (ctx) => PageThree(),
          defaultPageTransaction: CupertinoPageTransitionsBuilder()))
      .addRoute(NavigatorRoute('/four', (ctx) => PageFour(),
          defaultPageTransaction: ZoomPageTransitionsBuilder()))
      .addRoute(NavigatorRoute('/five', (ctx) => PageFive()))
      .addRoute(NavigatorRoute('/five/:id', (ctx) => PageFive()))
      .addRoute(NavigatorRoute('/print', (ctx) async {
        return Future.value('调用函数');
      }, responseProcessor: (c, p) async {
        print(p);
        return 'hello';
      }))
      .addRoute(NavigatorRoute('/showDialog', (ctx) async {
        return null;
      }, responseProcessor: (c, p) async {
        await RRouter.showDialog(
            routeSettings: RouteSettings(name: c.path, arguments: c.body),
            builder: (context) => AlertDialog(
                  title: Text('标题'),
                  content: Text('内容'),
                  actions: [
                    TextButton(
                        onPressed: () {
                          Navigator.pop(context);
                        },
                        child: Text('确定')),
                  ],
                ));
        return c.isDirectly == true ? Redirect(path: '/') : null;
      }))
      .setPageBuilder((ctx, builder, pageTransitionsBuilder) =>
          CustomPage<dynamic>(
              child: Builder(
                  builder: (BuildContext context) => builder.call(context)),
              buildCustomRoute:
                  (BuildContext context, CustomPage<dynamic> page) =>
                      PageBasedCustomPageRoute(
                          page: page,
                          pageTransitionsBuilder: pageTransitionsBuilder),
              key: ValueKey(ctx.at.microsecondsSinceEpoch),
              name: ctx.path,
              arguments: ctx.toJson(),
              transitionDuration: Duration(milliseconds: 100),
              restorationId: ctx.path))
      .setPopHome(() {
    return Future.value(true);
  });
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    // 使用Navigator 1.0
    // return MaterialApp(
    //   title: 'Flutter Demo',
    //   theme: ThemeData(
    //     primarySwatch: Colors.blue,
    //   ),
    //   navigatorObservers: [
    //     RRouter.observer,
    //   ],
    //   home: MyHomePage(title: 'Flutter Demo Home Page'),
    // );
    // 使用Navigator 2.0
    return MaterialApp.router(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      routerDelegate: RRouter.delegate,
      routeInformationParser: RRouter.informationParser,
    );
  }
}

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

1 回复

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


当然,下面是一个关于如何使用Flutter路由管理插件r_router的示例代码。这个示例将展示如何设置基本的路由管理,包括定义路由、导航到新页面以及处理参数传递。

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

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

然后运行flutter pub get来安装依赖。

1. 设置主路由文件

创建一个router.dart文件来定义你的路由配置。

import 'package:flutter/material.dart';
import 'package:r_router/r_router.dart';
import 'home_page.dart';
import 'detail_page.dart';

class MyRouter extends RRouter {
  @override
  List<RRoute> get routes => [
        RRoute(
          path: '/',
          builder: (_, __) => HomePage(),
        ),
        RRoute(
          path: '/detail/:id',
          builder: (_, params) => DetailPage(id: params['id']!),
        ),
      ];
}

2. 创建主页(Home Page)

创建一个home_page.dart文件来定义你的主页。

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

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final RRouter router = RRouter.of(context);

    return Scaffold(
      appBar: AppBar(
        title: Text('Home Page'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            router.navigateTo('/detail/123');
          },
          child: Text('Go to Detail Page'),
        ),
      ),
    );
  }
}

3. 创建详情页(Detail Page)

创建一个detail_page.dart文件来定义你的详情页。

import 'package:flutter/material.dart';

class DetailPage extends StatelessWidget {
  final String id;

  DetailPage({required this.id});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Detail Page'),
      ),
      body: Center(
        child: Text('Detail ID: $id'),
      ),
    );
  }
}

4. 在主应用中使用路由

最后,在你的main.dart文件中使用你定义的路由。

import 'package:flutter/material.dart';
import 'package:r_router/r_router.dart';
import 'router.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      navigatorKey: RRouter.navigatorKey,
      onGenerateRoute: (settings) {
        final MyRouter router = MyRouter();
        return router.generator(settings);
      },
      home: RRouterScope(
        router: MyRouter(),
        child: RBuilder(builder: (context, router) {
          return router.build('/');
        }),
      ),
    );
  }
}

在这个示例中,我们定义了一个简单的路由配置,包括一个主页和一个详情页。主页有一个按钮,点击按钮会导航到详情页,并传递一个ID参数。详情页会显示这个ID参数。

r_router插件允许你以声明式的方式定义路由,并且提供了方便的导航功能。通过这种方式,你可以更好地管理你的Flutter应用中的路由。

回到顶部