Flutter 导航系列 ---- go_router

891 阅读4分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第12天,点击查看活动详情

go_router 使用Flutter的路由器系统,但使用起来很容易。您需要使用两个主要类:

  • 路由器
  • 路线图

检查 GoRouter 组件

GoRouter 由以下组成:

  • 路线
  • 错误处理程序
  • 重定向处理程序

对于路线,GoRouter使用GoRoute. 这个类包含一个路径——比如一个 URL,一个可以用来代替路径的可选名称,以及一个返回页面的页面构建器或一个重定向到另一个路由的重定向处理程序。GoRoutes 甚至可以有子路由。这是您放置父路由调用的页面的地方。

go router 有一个redirect 选项,redirect 的 state 属性,可以用来写检查语句,查询当前路由:现在在哪里,去往哪里等等。有了这个,我们可以重定向到板载或不。

这很好,但我们将检查什么/如何检查?

这就是共享首选项的用武之地。我们可以使用共享首选项将简单数据存储在本地存储中。所以在应用程序初始化期间:

  1. 我们将获取存储在本地存储中的整数/密钥,它负责通过共享首选项保持对板载状态的计数。
  2. 首次启动应用程序时,共享首选项将返回 null,因为该整数尚不存在。对我们来说,这相当于从未入职的想法。
  3. 之后,在路由器上,我们将检查整数是否为空,如果是,则转到板载屏幕。
  4. 载入完成后,我们最终将在此处将不存在的整数设置为非空值,并使用 Provider 包将其保存在本地存储中。
  5. 现在当我们第二次再次启动应用程序时,路由器会发现整数不再是空值,所以它会重定向到我们的下一页而不是板载屏幕。
// Create enum to represent different routes
enum APP_PAGE {
  onboard,
  auth,
  home,
}
extension AppPageExtension on APP_PAGE {
  // create path for routes
  String get routePath {
    switch (this) {
      case APP_PAGE.home:
        return "/";      
      case APP_PAGE.onboard:
        return "/onboard";      
      case APP_PAGE.auth:
        return "/auth";      
      default:
        return "/";
    }
  }// for named routes
  String get routeName {
    switch (this) {
      case APP_PAGE.home:
        return "HOME";      
      case APP_PAGE.onboard:
        return "ONBOARD";    
      case APP_PAGE.auth:
        return "AUTH";      
      default:
        return "HOME";
    }
  }// for page titles to use on appbar
  String get routePageTitle {
    switch (this) {
      case APP_PAGE.home:
        return "Astha";      
      default:
        return "Astha";
    }
  }
}

Go Router

最后,我们可以转到路由器文件,我们将在其中创建路由和重定向逻辑。所以,在 app_router.dart 文件上。

创建一个AppRouter类。

import 'package:go_router/go_router.dart';
import 'package:temple/screens/home/home.dart';
import 'utils/router_utils.dart';class AppRouter  {
  get router => _router;  final _router = GoRouter(
      initialLocation: "/",
      routes: [
        GoRoute(
          path: APP_PAGE.home.routePath,
          name: APP_PAGE.home.routeName,
          builder: (context, state) => const Home(),
        ),
      ],
      redirect: (state) {});
}

AppRouter 是我们将用作提供者的路由器类。我们刚刚创建的路由器现在有一个路由器“/”,它是我们主页的路由。同样,initialLocation属性告诉路由器在应用程序启动后立即转到主页。但是,如果满足某些条件,则可以将其重定向到其他地方,这是通过重定向完成的。但是,我们还没有实现我们的路由器。为此,让我们转到 app.dart 文件。

使用路由器而不是导航器。

MaterialApp.Router 创建一个使用 Router 而不是 Navigator 的 MaterialApp。在这里查看差异。我们需要为我们的 go_router 使用声明方式。

Go-Router 重定向

// Packages
import 'package:go_router/go_router.dart';
import 'package:shared_preferences/shared_preferences.dart';
//Custom files
import 'package:temple/screens/home/home.dart';
import 'utils/router_utils.dart';
import 'package:temple/screens/onboard/onboard_screen.dart';
import 'package:temple/globals/providers/app_state_provider.dart';class AppRouter {
  AppRouter({
    required this.appStateProvider,
    required this.prefs,
  }); 
  AppStateProvider appStateProvider;
  late SharedPreferences prefs;
  get router => _router;
  late final _router = GoRouter(
      refreshListenable:
          appStateProvider,
      initialLocation: "/",
      routes: [
        GoRoute(
          path: APP_PAGE.home.routePath,
          name: APP_PAGE.home.routeName,
          builder: (context, state) => const Home(),
        ),
        GoRoute(
            path: APP_PAGE.onboard.routePath,
            name: APP_PAGE.onboard.routeName,
            builder: (context, state) => const OnBoardScreen()
         ),
      ],
      redirect: (state) {
        final String onboardPath =
            state.namedLocation(APP_PAGE.onboard.routeName); 
        bool isOnboarding = state.subloc == onboardPath; 
        bool toOnboard =
            prefs.containsKey('onBoardCount') ? false : true; 
        if (toOnboard) {
          return isOnboarding ? null : onboardPath;
        }
        return null; 
      });
}

让我们来看看我们所做的更改。

  1. 我们创建了两个类文件:appStateRouter 和 prefs。需要SharedPrefences 实例首选项来检查我们是否已经加入,基于板载计数整数的存在。appStateProvider 将提供对路由器重要的所有更改。
  2. 路由器属性refreshListenableTo设置为监听来自 appStateProvider 的更改。
  3. 我们将 OnBoardScreen 路由添加到路由列表中。
  4. 在这里,我们,
  • 首先为板载屏幕创建一个命名位置。
  • 然后isOnboarding检查当前路线(state.subloc)是否朝向板载屏幕。
  • 如果本地存储已经有onBoardCount整数,那么我们不会加入,否则我们会加入。
  • 根据toOnboard的值,我们将返回 null 或onBoardPath以重定向到。我们检查了当前路线是否使用isOboarding 前往 onBoardScreen 如果是,则返回 null。我们需要这样做,否则路由器将进入循环并导致错误。******
  • 最后,如果我们不必在任何地方重定向,则返回 null 告诉路由器暂时忽略重定向。