DEV Community

مصعب يوسف
مصعب يوسف

Posted on Originally published at ms3byoussef.medium.com

Generated Code in Flutter ”AutoRoute”

Improve Flutter Developer Skills ‘AutoRoute Package’

Generated Code in Flutter ”AutoRoute”

“Peace be upon you “

We all know that everyone wants to reach the maximum stages of development in work and science, This is no different when you work in the field of mobile application development, Especially with Google developers who have developed flutter the most amazing framework which contains many useful libraries, one of which we will talk about:
auto_route with injectable && get_it

What is routing?

In Flutter, routing refers to the mechanism for navigating between different screens or pages within your application. It’s essentially how users flow through your app and access information.

Here’s a breakdown of the concept:

  • Screens as Routes: Each screen in your Flutter app is considered a route. It’s a Widget that builds the UI for that particular screen.
  • Navigator Widget: The core of routing in Flutter is the Navigator class. This class, typically provided by MaterialApp or CupertinoApp, manages the navigation stack and transitions between routes.
  • Navigation Methods: The Navigator provides methods for pushing new routes onto the stack (like pushing a new screen on top) and popping routes off (going back to the previous screen). Common methods include push and pop.

Why AutoRoute?

AutoRoute is a popular routing package for Flutter that simplifies navigation management within your app. It offers several advantages over basic routing:

Code Generation: AutoRoute uses code generation to automate a lot of the boilerplate code associated with routing. You define your routes using annotations, and the package generates the necessary classes and methods for navigation. This reduces development time and improves code readability.

Type Safety: AutoRoute enforces type safety for arguments passed between screens. This helps prevent errors and makes your code more maintainable.

Deep Linking: AutoRoute simplifies deep linking, a feature that allows users to navigate to specific parts of your app from a URL. This is useful for sharing specific content or functionality within your app.

Other Features: AutoRoute offers additional features like nested navigation (handling tabs within your navigation flow) and guarded routes (restricting access to certain screens based on conditions).

Here’s a quick overview of how AutoRoute works:

  1. Define Routes: You define your app’s routes using annotations like @RoutePage on your screen widgets.
  2. Generate Code: You run a command to generate code based on your route definitions. This creates classes and methods for navigation.
  3. Navigate: You use the generated router object to navigate between screens. AutoRoute handles argument passing, deep linking, and transitions automatically.

Get started

To get started, add auto_route to your pubspec.yaml. We also need to add auto_route_generator and get_it and build_runner to generate our routes.

Generated Code in Flutter ”AutoRoute”

Benefits of Injectable:

  • Reduced Boilerplate: Injectable eliminates the need to write manual code for registering and retrieving dependencies with GetIt. This saves development time and improves code clarity.
  • Improved Maintainability: By keeping dependency configuration centralized with annotations, Injectable makes it easier to manage and update dependencies throughout your app.
  • Testability: Since dependencies are injected, you can easily mock them during testing, isolating the behavior of your classes.

you can see in our Series

Route Configuration

Lets add Auto Router configuration to your app:

Create a router class and annotate it with @AutoRouterConfig then extend "_$AppRouter"

in old version @MaterialAutoRoute()

  1. Override the routes getter
// ignore_for_file: override_on_non_overriding_member

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

import 'app_router.gr.dart';

@AutoRouterConfig(replaceInRouteName: 'Screen,Route')
class AppRouter extends $AppRouter {
  AppRouter(GlobalKey<NavigatorState> navigatorKey);

  @override
  List<AutoRoute> get routes => [
        AutoRoute(
          path: '/home',initial: true, page: HomeRoute.page,
          children: [
        AutoRoute(page: ProfilePage, guards: [AuthGuard()],), // List of guards to check
          ],
        ),
      ];
}
Enter fullscreen mode Exit fullscreen mode

using guards with auto_route in a Flutter app to restrict access to a specific route:

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

// Define a custom Guard class
class AuthGuard extends AutoRouteGuard {
  @override
  void onNavigation(NavigationRedirect redirect) {
    // Check if user is authenticated (replace with your logic)
    final isAuthenticated = false; // Replace with actual authentication check
    if (!isAuthenticated) {
      // Redirect to Login if not authenticated
      redirect.push(LoginPage());
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

in page you chose:

add @RoutePage()

import 'package:auto_route/annotations.dart';
import 'package:flutter/material.dart';

import 'widgets/users_view_body.dart';

@RoutePage()
class UsersScreen extends StatelessWidget {
  const UsersScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      body: UsersViewBody(),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

Now simply run build_runner to generate our route, run one of commands below

(I recommend watch)

// to watch the files's system edits and rebuild as necessary
dart run build_runner watch

// to run build_runner just once
dart run build_runner build --delete-conflicting-outputs
Enter fullscreen mode Exit fullscreen mode

put our router configuration let’s hook it up to MaterialApp

class MyApp extends StatelessWidget {
  MyApp({super.key});

  /// create an instance of `AppRouter`
  final _appRouter = AppRouter();

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      // hook up router to MaterialApp
      routerConfig: _appRouter.config(),
    );
  }
Enter fullscreen mode Exit fullscreen mode
  • We define an InjectableModule for registering services.
  • We create an AuthGuard class that injects the AppRouter and checks for authentication before navigation.
  • In the router definition, we apply the AuthGuard to specific routes

Generated Code in Flutter ”AutoRoute”

AppRouter wit get_it can we accessed anywhere in the app without context

getIt().push(widgetRouter)

// assuming this is the root widget of your App
class App extends StatelessWidget {
  // make sure you don't initiate your router
  // inside of the build function.
  final _appRouter = AppRouter();

  @override
  Widget build(BuildContext context){
    return MaterialApp.router(
      routerConfig: _appRouter.config(),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

After you run the generator, your router class will be generated. Then simply hook it up with your MaterialApp.

you can use push

getIt().push(widgetRouter)

you can use pop

getIt().pop()

in new version

getIt().pop()

Nested Navigation

Nested navigation means building an inner router inside of a page of another router, for example in the below diagram users page is built inside of dashboard page.

@AutoRouterConfig(replaceInRouteName: 'Page,Route')
class AppRouter extends $AppRouter {

@override
List<AutoRoute> get routes => [
    AutoRoute(
      path: '/dashboard',
      page: DashboardRoute.page,
      children: [
        AutoRoute(path: 'users', page: UsersRoute.page),
        AutoRoute(path: 'posts', page: PostsRoute.page),
        AutoRoute(path: 'settings', page: SettingsRoute.page),
      ],
    ),
    AutoRoute(path: '/login', page: LoginRoute.page,gards:AuthGards()),
  ];
}
Enter fullscreen mode Exit fullscreen mode

Generated Code in Flutter ”AutoRoute”

Nested Tab navigation

Some apps display destinations in a subsection of the screen, for example, a BottomNavigationBar that stays on-screen when navigating between Screens.

Since this is not an easy task to implement with Flutter apps auto_route makes tabs navigation as easy and straightforward as possible.

We’ll use AutoTabsRouter to handle tab navigation

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

we can learn about Nested Navigation && Tab Navigation &&Using TabBar

in the documentation of package that’s awesome

https://pub.dev/packages/auto_route#nested-navigation

Generated Code in Flutter ”AutoRoute”

To Improved developer experience with reduced boilerplate code, Type safety with strongly-typed arguments. Deep linking capabilities. Increased control over navigation with guards and transitions you should use **Auto\_route**

Remember: AutoRoute works seamlessly with dependency injection frameworks like GetIt and Injectable. You can inject required services into your screens using these frameworks while utilizing AutoRoute for navigation.

References

https://pub.dev/packages/auto_routehttps://medium.com/@antonio.tioypedro1234/flutter-auto-route-guide-9ac405e8a941

https://www.youtube.com/watch?v=KzqKfYypvqs


Originally published on Medium on July 13, 2024.

Top comments (0)