Что такое Go Router в контексте Flutter?

Ответ

Go Router — это популярный, мощный и декларативный пакет для маршрутизации (навигации) в Flutter-приложениях. Он служит заменой стандартному Navigator, предлагая удобный API для работы со сложной навигацией, глубокими ссылками и защитой маршрутов.

Базовый пример настройки:

final _router = GoRouter(
  routes: [
    GoRoute(
      path: '/',
      builder: (context, state) => const HomeScreen(),
    ),
    GoRoute(
      path: '/profile/:userId',
      builder: (context, state) {
        final userId = state.pathParameters['userId']!;
        return ProfileScreen(userId: userId);
      },
    ),
    GoRoute(
      path: '/settings',
      builder: (context, state) => const SettingsScreen(),
      routes: [
        // Вложенный маршрут
        GoRoute(
          path: 'theme',
          builder: (context, state) => const ThemeSettingsScreen(),
        ),
      ],
    ),
  ],
  // Редирект для проверки аутентификации
  redirect: (context, state) {
    final isLoggedIn = AuthService.isLoggedIn;
    final goingToLogin = state.matchedLocation == '/login';
    if (!isLoggedIn && !goingToLogin) return '/login';
    if (isLoggedIn && goingToLogin) return '/';
    return null; // Разрешить навигацию
  },
);

// В MaterialApp
MaterialApp.router(
  routerConfig: _router,
);

Ключевые возможности Go Router:

  • Декларативная конфигурация маршрутов в одном месте.
  • Глубокие ссылки (deeplinking) — работа с URL из браузера или push-уведомлений.
  • Защита маршрутов через логику redirect (например, для аутентификации).
  • Вложенная навигация для организации сложных UI (например, вкладок с собственным стеком).
  • Удобная передача параметров через state.pathParameters и state.uri.queryParameters.

Навигация:

context.go('/profile/123'); // Замена всего стека
context.push('/settings/theme'); // Добавление поверх стека
GoRouter.of(context).pop(); // Назад

Ответ 18+ 🔞

Ну, слушай, история про Go Router — это просто ёперный театр для тех, кто намаялся с нативным Navigator. Представь, что тебе надо просто перейти с экрана на экран, а ты уже пишешь код, как будто разминируешь бомбу. А тут — раз, и всё красиво и понятно.

Вот смотри, как это выглядит в жизни. Берёшь и объявляешь маршрутизатор, как начальник штаба расставляет флажки на карте.

final _router = GoRouter(
  routes: [
    GoRoute(
      path: '/',
      builder: (context, state) => const HomeScreen(),
    ),
    GoRoute(
      path: '/profile/:userId',
      builder: (context, state) {
        final userId = state.pathParameters['userId']!;
        return ProfileScreen(userId: userId);
      },
    ),
    GoRoute(
      path: '/settings',
      builder: (context, state) => const SettingsScreen(),
      routes: [
        // Вложенный маршрут
        GoRoute(
          path: 'theme',
          builder: (context, state) => const ThemeSettingsScreen(),
        ),
      ],
    ),
  ],
  // Редирект для проверки аутентификации
  redirect: (context, state) {
    final isLoggedIn = AuthService.isLoggedIn;
    final goingToLogin = state.matchedLocation == '/login';
    if (!isLoggedIn && !goingToLogin) return '/login';
    if (isLoggedIn && goingToLogin) return '/';
    return null; // Разрешить навигацию
  },
);

// В MaterialApp
MaterialApp.router(
  routerConfig: _router,
);

Видишь эту штуку redirect? Это же гениально! Раньше ты на каждом экране вручную проверял, залогинен ли юзер, а если нет — выпинывал его на авторизацию. Головняк был овердохуища. А теперь ты в одном месте пишешь логику, и она работает на всю приложуху. Чувак, это как поставить умного швейцара на вход, который сам решает, кого пускать, а кого послать нахуй. Подозрение ебать чувствую, что без такого редиректа раньше в приложение мог зайти кто угодно.

А вложенные маршруты — это вообще песня. Раньше чтобы сделать вкладки, у каждой из которых свой стек экранов, нужно было танцевать с бубном и IndexedStack. Теперь же ты просто пишешь routes внутри другого GoRoute, и всё, пизда рулю. Красота.

На чём он вообще силён, этот Go Router:

  • Всё в одном месте. Не надо искать, где и как объявлен переход. Открыл один файл — и видишь всю карту приложения. Удивление пиздец, как же раньше без этого жили.
  • Глубокие ссылки. Это когда тебе в пуш-уведомлении прилетает ссылка типа myapp://product/123, и ты по ней попадаешь прямиком в нужное место. Раньше это была боль, а сейчас — обычный вторник. Настраиваешь path — и всё, хуй с горы, работает.
  • Защита, как в банке. Через этот самый redirect ты можешь проверять что угодно: авторизацию, подписку, согласие на условия. Если что-то не так — пользователь даже не увидит контента, его мягко перенаправят куда надо.
  • Параметры из URL. Видел в path :userId? Это placeholder. Когда юзер зайдёт по ссылке /profile/vasya_pupkin, ты легко вытащишь это vasya_pupkin из state.pathParameters. А если в URL ещё и ?ref=promo будет, то и это достанешь из queryParameters. Удобно, бля буду.

Как по этой карте ходить:

context.go('/profile/123'); // Жёсткая замена всего стека. Старое — к херам, показываем новое.
context.push('/settings/theme'); // Классический переход. Добавляем экран поверх стека.
GoRouter.of(context).pop(); // Назад, на предыдущий экран. Всё как у людей.

В общем, если ты ещё сидишь на старом Navigator.of(context).push(MaterialPageRoute(builder: ...)) для каждого перехода, то, ядрёна вошь, пора бы уже в двадцать первый век переползать. Go Router — это не просто пакет, это философия. Сначала, конечно, придётся голову поломать, но когда вникнешь — жить станет проще, вот ты веришь, чувак?