Расширенный пакет навигации Flutter

Минималистское руководство по расширенной навигации с использованием Navigator v2.0 во Flutter с AutoRoute

Почему АвтоРут?

Навигатор 2.0 великолепен! но, как и все, мы знаем, что это действительно трудно понять!

В этом случае AutoRoute помогает легко использовать nav2 декларативным способом!

AutoRoute избавляет нас от написания большого количества стандартного кода для классов аргументов-посредников, проверки обязательных аргументов, извлечения аргументов и множества других вещей и т. д.

Почему не другие, а AutoRoute? Потому что это дает нам как довольно короткий синтаксис, так и расширенные функции со стабильностью!

Функции

  • Именованные маршруты
  • Параметры пути и сопоставление подстановочных знаков
  • Вложенные маршруты и маршрутизаторы
  • Настраиваемые переходы маршрута
  • Глубокие ссылки
  • Охранники маршрута
  • Простая маршрутизация нижней панели навигации
  • Декларативная маршрутизация
  • Маршрутизация потока

И многое, многое другое из коробки…

Теперь давайте посмотрим, как его использовать!

Быстрый старт

Шаг 1. Создайте настройки навигации

// @CupertinoAutoRouter
// @AdaptiveAutoRouter
// @CustomAutoRouter
@MaterialAutoRouter(
  // Name Shortener - HomePage → HomeRoute instead of HomePageRoute
  replaceInRouteName: 'Page,Route',
  routes: <AutoRoute>[
    AutoRoute(page: HomePage, initial: true),
    AutoRoute(page: Products),
    AutoRoute(page: ProductDetailsPage),
    RedirectRoute(path: '*', redirectTo: '/'),
  ],
)
class $AppRouter {}

Шаг 2

flutter packages pub run build_runner build 

Шаг 3

Создайте глобальный экземпляр (также вы можете использовать локатор сервисов, например get_it)

final appRouter = AppRouter();

Шаг 4

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
@override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      routerDelegate: appRouter.delegate(),
      routeInformationParser: appRouter.defaultRouteParser(),
    );
  }
}

Шаг 5

Используйте его, как хотите!

context.push(const ProductsRoute()); // with context
appRouter.push(const ProductsRoute()); // without context

Давайте глубоко погрузимся в пакет !!

Прежде чем мы начнем, я хочу сказать, что не буду описывать основные функции, которые есть в каждом пакете! вместо этого я расскажу только о дополнительных функциях, которые делают AutoRoute уникальным и красивым!

Обозреватели (промежуточное ПО)

Будь большим братом, который следит за маршрутом!

class CustomObserver implements AutoRouterObserver {
  @override
  void didChangeTabRoute(TabPageRoute route, TabPageRoute previousRoute) {}
  @override
  void didInitTabRoute(TabPageRoute route, TabPageRoute? previousRoute) {}
  @override
  void didPop(Route route, Route? previousRoute) {}
  @override
  void didPush(Route route, Route? previousRoute) {}
  @override
  void didRemove(Route route, Route? previousRoute) {}
  @override
  void didReplace({Route? newRoute, Route? oldRoute}) {}
  @override
  void didStartUserGesture(Route route, Route? previousRoute) {}
  @override
  void didStopUserGesture() {}
  @override
  NavigatorState? get navigator => throw UnimplementedError();
}

2. Добавьте своего наблюдателя к делегату

MaterialApp.router(
  routerDelegate: appRouter.delegate(
    navigatorObservers: () => [
      CustomObserver(),
      FirebaseAnalyticsObserver(analytics: FirebaseAnalytics()),
    ],
  ),
);

Параметры пути (динамический URL)

Шаг 1. Определите путь

AutoRoute(path: '/books/:bookId', page: BookDetailsPage)

Шаг 2. Аннотируйте параметр в конструкторе

class BookDetailsPage extends StatelessWidget {
    BookDetailsPage({@pathParam this.bookId}); 
    final int bookId;
    ...

Параметры запроса

Точно так же можно получить доступ к параметрам запроса!

context.route.queryParams
// or
class BookDetailsPage extends StatelessWidget {            
  const BookDetailsPage({@queryParam this.id});        
          
  final int id;            
  ...

перенаправление

Давайте посмотрим, как легко перенаправить!

<AutoRoute> [
    RedirectRoute(path: '/', redirectTo: '/books'),
    AutoRoute(path: '/books', page: BooksPage),
]

Подстановочные знаки

Вы хотите использовать подстановочные знаки? без проблем!

AutoRoute(path: '/books/*', page: BooksPage) 
RedirectRoute(path: '*', redirectTo: '/')

Глубокие ссылки

MaterialApp.router(
  routerDelegate: appRouter.delegate(
    initialDeepLink: ‘PATH’
  ),
);

RouteGuards (промежуточное ПО)

Вы можете легко сделать собственные охранники для ваших маршрутов!

  1. Создайте свою охрану
class AuthGuard extends AutoRouteGuard {        
  @override        
  void onNavigation(resolver, router) {    
    if(unauthenticated) resolver.next(true);
    else router.push(LoginRoute());        
  }
}

2. Назначьте охранников на маршруты, которые вы хотите использовать

AutoRoute(page: ProfileScreen, guards: [AuthGuard]);

3. Запустите генерацию кода и добавьте сгенерированный класс Guard в класс AppRouter.

final _appRouter = AppRouter(authGuard: AuthGuard());

AutoLeadingButton / BackButton

AutoLeadingButton — это замена AutoRoute кнопки BackButton по умолчанию для обработки вложенного или родительского стека.

AppBar(    
  leading: AutoLeadingButton(),  
  ...  
)

Вложенная навигация

Просто добавьте маршруты в параметр Children, вот и все!!

AutoRoute(            
  path: '/dashboard',            
  page: DashboardPage,            
  children: [            
    AutoRoute(path: 'users', page: UsersPage),            
    AutoRoute(path: 'posts', page: PostsPage),        
    AutoRoute(path: 'settings', page: SettingsPage),              
  ],            
)

class DashboardPage extends StatelessWidget {        
  @override        
  Widget build(BuildContext context) {        
    return Row(        
      children: [        
        Column(        
          children: [      
            TextButton(
              child: const Text('Users'),
              onPressed: () {
                appRouter.push(const UsersRoute());
              },
            ),
            TextButton(
              child: const Text('Posts'),
              onPressed: () {
                appRouter.push(const PostsRoute());
              },
            ),
            TextButton(
              child: const Text('Settings'),
              onPressed: () {
                appRouter.push(const SettingsRoute());
              },
            ),
          ],        
        ),        
        Expanded(        
          // nested routes will be rendered here        
          child: AutoRouter(),        
        ),        
      ],        
    );        
  }        
}

Навигация по вкладкам

Вам надоела длинная реализация TabBar по умолчанию?

AutoRoute также дает нам довольно удобный способ!

Кстати, вкладки по умолчанию загружаются отложенно, но их тоже можно отключить!

class DashboardPage extends StatelessWidget {               
  @override        
  Widget build(context) {        
    return AutoTabsScaffold(        
       routes: const [        
        UsersRoute(),        
        PostsRoute(),        
        SettingsRoute(),        
      ],        
      bottomNavigationBuilder: (_,tabsRouter) {        
        return BottomNavigationBar(        
          currentIndex: tabsRouter.activeIndex,        
          onTap: tabsRouter.setActiveIndex,        
          items: [        
            BottomNavigationBarItem(label: 'Users',...),        
            BottomNavigationBarItem(label: 'Posts',...),        
            BottomNavigationBarItem(label: 'Settings',...),        
          ],        
        ),
      ),               
    }        
  );        
}

Примечание. Вы даже можете реализовать PageView или TabBar, просто добавив конструкторы имен!

AutoTabsRouter.pageView(...);
AutoTabsRouter.tabBar(...);

Вы хотите добраться до контроллеров отовсюду? Это так просто!

router.parent<StackRouter>(); // returns Stack Routing controller            
router.parent<TabsRouter>(); // returns Tabs Routing controller
router.root; // returns Stack Routing controller

Вот и все? Нисколько! Есть еще!! Такой как;

  • Пользовательские переходы
  • Пользовательские конструкторы маршрутов
  • Обертывание маршрутов
  • RouteAwareStateMixins
  • Еще более декларативная навигация и другие…

Для получения дополнительной информации, пожалуйста, ознакомьтесь с документацией!

Спасибо за чтение!

Я постарался объяснить как можно проще. Надеюсь, вам понравится.

Если вам понравилась эта статья, нажмите кнопку 👏 (знали ли вы, что можете дойти до 50?)