首页 > 其他分享 >flutter开发实战-go_router使用

flutter开发实战-go_router使用

时间:2024-07-29 16:28:45浏览次数:13  
标签:return id context go router flutter const

flutter开发实战-go_router使用

在这里插入图片描述

一、go_router介绍与特性

go_router是一个Flutter的第三方声明式路由插件,使用路由器API提供一个方便的、基于url的API,用于在不同屏幕之间导航。可以定义URL模式、使用URL导航、处理深度链接以及许多其他与导航相关的场景。

GoRouter具有许多功能,使导航变得简单明了:

  • 使用模板语法解析路由路径和路由查询(query)参数;
  • 支持单个目标路由展示多个页面(子路由);
  • 重定向:可以基于应用状态跳转到不同的URL,比如用户没有登录时跳转到登录页;
  • 使用 StatefulShellRoute 可以支持嵌套的 Tab 导航;
  • 同时支持 Material 风格和 Cupertino 风格应用;
  • 兼容 Navigator API 。

二、引入go_router

根据自己需要的版本引入对应的版本,在pubspec.yaml加入

  go_router: ^8.2.0
    

稍后执行flutter pub get命令

三、go_router路由配置

引入插件后,我们需要配置MaterialApp.router的routerConfig

/// The route configuration.
final GoRouter _router = GoRouter(
  routes: <RouteBase>[
    GoRoute(
      path: '/',
      builder: (BuildContext context, GoRouterState state) {
        return const HomeScreen();
      },
      routes: <RouteBase>[
        GoRoute(
          path: 'details',
          builder: (BuildContext context, GoRouterState state) {
            return const DetailsScreen();
          },
        ),
      ],
    ),
  ],
);
    

配置MaterialApp.router

/// The main app.
class MyApp extends StatelessWidget {
  /// Constructs a [MyApp]
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      routerConfig: _router,
    );
  }
}
    

四、go_router路由跳转

如果跳转页面,可以使用content.go

context.go('/details')

4.1、路径参数

GoRouter 的每一个路由都通过 GoRoute对象来配置,可以通过路径参数进行传递相关参数到目标页面。例如路径comment/参数id

GoRoute(
          path: 'comment/:id',
          builder: (BuildContext context, GoRouterState state) {
            String? id = state.pathParameters['id'];
            print("id:${id}");// Get "id" param from URL
            return CommentScreen(id: id);
          },
        ),

那么可以通过context.go(’/comment/55555’)传参数

ElevatedButton(
          onPressed: () => context.go('/comment/55555'),
          child: const Text('Go to the comment screen'),
        )

4.2、路径查询参数

可以获取路径的查询参数 URL 路径中的查询(query)参数,例如从/search?keyword=myname中获取search参数。

GoRoute(
          path: 'search',
          builder: (BuildContext context, GoRouterState state) {
            String? keyword = state.queryParameters['keyword'];
            print("keyword:${keyword}"); // Get "id" param from URL
            return SearchScreen(keyword: keyword);
          },
        ),

传递参数context.go(’/search?keyword=myName’)目标页面可以得到参数myName

ElevatedButton(
              onPressed: () => context.go('/search?keyword=myName'),
              child: const Text('Go to the Search screen'),
            ),

五、添加子路由

子路由,路由匹配支持多个页面,当一个新的页面在旧的页面之上展示时

GoRoute(
          path: 'details',
          builder: (BuildContext context, GoRouterState state) {
            return const DetailsScreen();
          },
          routes: <RouteBase>[
            // Add child routes
            GoRoute(
              path: 'sub-details',
              // NOTE: Don't need to specify "/" character for router’s parents
              builder: (context, state) {
                return SubDetailsScreen();
              },
            ),
          ],
        ),

可以通过context.go(’/details/sub-details’)来进行调用

ElevatedButton(
              onPressed: () => context.go('/details/sub-details'),
              child: const Text('Go to the SubDetails screen'),
            ),

六、页面导航

go_router提供多种方式进行跳转

context.goNamed方式

ElevatedButton(
              onPressed: () => context.goNamed('/details'),
              child: const Text('Go to the Details screen'),
            ),

七、路由重定向

go_router提供全局重定向,比如在没有登录的用户,需要跳转到登录页面.在 GoRouter 中,可以通过redirect 参数配置重定向.

redirect: (BuildContext context, GoRouterState state) {
    final isLogin = false;// your logic to check if user is authenticated
    if (!isLogin) {
      return '/login';
    } else {
      return null; // return "null" to display the intended route without redirecting
    }
  }

八、错误处理(404页面)

go_router为MaterialApp 和CupertinoApp定义了默认的错误页面,也可以通过 errorBuilder 参数自定义错误页面。

errorBuilder: (
    BuildContext context,
    GoRouterState state,
  ) {
    // ErrorPage
    return ErrorScreen();
  }

九、路由跳转监测

在flutter自带的会有NavigatorObserver,go_router页提供路由跳转监测功能

class MyNavigatorObserver extends NavigatorObserver {
  @override
  void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {
    print('did push route');
  }

  @override
  void didPop(Route<dynamic> route, Route<dynamic>? previousRoute) {
    print('did pop route');
  }
}

在observers中配置

GoRouter(
  observers: [MyNavigatorObserver()],
...
)

这里只是代码尝试了一下常用功能。还有一些转场动画、嵌套导航等等特性需要去尝试。
可以查看https://juejin.cn/post/7270343009790853172

注意:不同版本的代码有所不同。

测试的完整代码如下

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

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

class MyNavigatorObserver extends NavigatorObserver {
  @override
  void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {
    print('did push route');
  }

  @override
  void didPop(Route<dynamic> route, Route<dynamic>? previousRoute) {
    print('did pop route');
  }
}

/// The route configuration.
final GoRouter _router = GoRouter(
  observers: [MyNavigatorObserver()],
  redirect: (BuildContext context, GoRouterState state) {
    final isLogin = false; // your logic to check if user is authenticated
    if (!isLogin) {
      return '/login';
    } else {
      return null; // return "null" to display the intended route without redirecting
    }
  },
  errorBuilder: (
    BuildContext context,
    GoRouterState state,
  ) {
    // ErrorPage
    return ErrorScreen();
  },
  routes: <RouteBase>[
    GoRoute(
      path: '/',
      builder: (BuildContext context, GoRouterState state) {
        return const HomeScreen();
      },
      routes: <RouteBase>[
        GoRoute(
          path: 'details',
          builder: (BuildContext context, GoRouterState state) {
            return const DetailsScreen();
          },
          routes: <RouteBase>[
            // Add child routes
            GoRoute(
              path: 'sub-details',
              // NOTE: Don't need to specify "/" character for router’s parents
              builder: (context, state) {
                return SubDetailsScreen();
              },
            ),
          ],
        ),
        GoRoute(
          path: 'comment/:id',
          builder: (BuildContext context, GoRouterState state) {
            String? id = state.pathParameters['id'];
            print("id:${id}"); // Get "id" param from URL
            return CommentScreen(id: id);
          },
        ),
        GoRoute(
          path: 'search',
          builder: (BuildContext context, GoRouterState state) {
            String? keyword = state.queryParameters['keyword'];
            print("keyword:${keyword}"); // Get "id" param from URL
            return SearchScreen(keyword: keyword);
          },
        ),
      ],
    ),
  ],
);

/// The main app.
class MyApp extends StatelessWidget {
  /// Constructs a [MyApp]
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      routerConfig: _router,
    );
  }
}

/// The home screen
class HomeScreen extends StatelessWidget {
  /// Constructs a [HomeScreen]
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Home Screen')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            ElevatedButton(
              onPressed: () => context.goNamed('/details'),
              child: const Text('Go to the Details screen'),
            ),
            SizedBox(
              height: 30,
            ),
            ElevatedButton(
              onPressed: () => context.go('/details/sub-details'),
              child: const Text('Go to the SubDetails screen'),
            ),
          ],
        ),
      ),
    );
  }
}

/// The details screen
class DetailsScreen extends StatelessWidget {
  /// Constructs a [DetailsScreen]
  const DetailsScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Details Screen')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            ElevatedButton(
              onPressed: () => context.go('/comment/55555'),
              child: const Text('Go to the comment screen'),
            ),
            SizedBox(
              height: 30,
            ),
            ElevatedButton(
              onPressed: () => context.go('/search?keyword=myName'),
              child: const Text('Go to the Search screen'),
            ),
          ],
        ),
      ),
    );
  }
}

/// The details screen
class SubDetailsScreen extends StatelessWidget {
  /// Constructs a [SubDetailsScreen]
  const SubDetailsScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('SubDetailsScreen Screen')),
      body: Center(
        child: ElevatedButton(
          onPressed: () => context.go('/details'),
          child: const Text('Go back to the Details screen'),
        ),
      ),
    );
  }
}

/// The details screen
class CommentScreen extends StatelessWidget {
  /// Constructs a [DetailsScreen]
  const CommentScreen({super.key, this.id});

  final String? id;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('CommentScreen Screen')),
      body: Center(
          child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          Text("param id:${id}"),
          SizedBox(
            height: 30,
          ),
          ElevatedButton(
            onPressed: () => context.go('/'),
            child: const Text('Go back to the Details screen'),
          ),
        ],
      )),
    );
  }
}

/// The Search screen
class SearchScreen extends StatelessWidget {
  /// Constructs a [DetailsScreen]
  const SearchScreen({super.key, this.keyword});

  final String? keyword;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('SearchScreen Screen')),
      body: Center(
          child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          Text("param keyword:${keyword}"),
          SizedBox(
            height: 30,
          ),
          ElevatedButton(
            onPressed: () => context.go('/'),
            child: const Text('Go back to the details screen'),
          ),
        ],
      )),
    );
  }
}

/// The Search screen
class ErrorScreen extends StatelessWidget {
  /// Constructs a [DetailsScreen]
  const ErrorScreen();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('ErrorScreen Screen')),
      body: Center(
        child: Container(
          child: const Text('Error info'),
        ),
      ),
    );
  }
}

十、小结

flutter开发实战-go_router使用

学习记录,每天不停进步。

标签:return,id,context,go,router,flutter,const
From: https://blog.csdn.net/gloryFlow/article/details/140772830

相关文章

  • 如何在django项目中设置login_required,我没有使用django inbuild身份验证登录?
    用户无法通过输入任何页面的url进入任何页面我是否需要更改设置中的任何内容.py我没有使用django内置身份验证进行登录。view.py用于登录每个仪表板,defasset_login(request):ifrequest.method=='POST':username=request.POST.get('user_id')passw......
  • Django 页面不显示任何内容
    我的“新闻”页面无法正常工作,它正在数据库中保存信息,但不显示任何内容。这里是HTML:{%extends'base.html'%}{%blockcontent%}<h1class='product'>News</h1>{%foriteminnew%}<div><br><strong><ahref='/news/{{item.......
  • 论文摘要:Efficient Algorithms for Densest Subgraph Discovery on Large Directed Gr
    背景在很多应用中,例如欺诈检测、社区挖掘和图压缩等,需要从有向图中找到密度最高的子图,这被称为有向最密子图问题(DirectedDensestSubgraph,DDS)。DDS问题在社交网络、Web图和知识图谱等领域有着广泛的应用。例如,在社交网络中,可以用来检测假粉丝,在Web图中,可以用来发现网络......
  • pymongo版本更新错误DatetimeConversion
    由于我使用的是pymongo版本3.6.0,现在更新到版本4.6.3,在此更新之后,我可以执行构建并开始运行。但在单元测试中,我的错误为“ImportError:无法从'bson.code_option'(~/bmstmp/dockcont1/configs/main/pybuild/x86_64-v21/Debug/bson/codec_options.py)导入名称'DatetimeC......
  • go画蜡烛图
     GPT-4o(OpenAI) 要在Go语言中画蜡烛图(又称K线图),你可以使用一些图形库,如chart或go-echarts。下面是一个使用go-echarts库绘制蜡烛图的示例:首先,你需要安装go-echarts库。可以通过以下命令安装:goget-ugithub.com/go-echarts/go-echarts/v2接下来是一个简单的例......
  • ARFoundation系列讲解 - 93 Immersal GoPro绘制地图
    一、Immerasal地图绘制的方式1.MapperAPP地图绘制:这种⽅式不需要数据处理操作,更适合⼩场景、测试使⽤。只能生成点云模型,无法生成真实环境网格模型。2. 全景相机地图绘制:使⽤全景相机采集原始数据建图的优势在于:全景图⽚视野覆盖范围⼤,可以⽤更少的照⽚完成较⼤场景地图(......
  • 计算机毕业设计django+vue保险业务信息管理系统【开题+论文+程序】
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景随着保险行业的蓬勃发展,保险业务量的激增对保险公司的信息管理提出了更高的要求。传统的业务管理方式往往依赖于人工操作和纸质文档,不仅效......
  • 计算机毕业设计django+vueHPV疫苗预约系统【开题+论文+程序】
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景随着社会对健康重视程度的日益提升,疫苗接种成为了预防疾病、保障公众健康的重要措施。其中,HPV(人乳头瘤病毒)疫苗作为预防宫颈癌等严重疾病......
  • 如何使用Visual Studio代码调试django
    我是django开发领域的新人,使用Xcode和相关IDE进行桌面/移动应用程序开发。我必须使用Django,我想知道是否有一个高效的使用VisualStudioCode(或Atom)进行调试的方法。与DjangoIDE相关的任何帮助也会有所帮助。使用VisualStu......
  • Lambda-Go:将函数式编程引入 Go
    Lambda-Go:将函数式编程引入Go原创 GoOfficialBlog GoOfficialBlog 2024年07月28日20:16 中国香港函数式编程是编程范式当中的一种,喜欢的人爱之如命,不喜欢的人嗤之以鼻,以简单高效著称的Go天然在函数式编程上有自己的优势。Lambda-Go[1] 是一个旨在将受Haskell......