Close Menu
    DevStackTipsDevStackTips
    • Home
    • News & Updates
      1. Tech & Work
      2. View All

      Coded Smorgasbord: High Strung

      September 26, 2025

      Chainguard launches trusted collection of verified JavaScript libraries

      September 26, 2025

      CData launches Connect AI to provide agents access to enterprise data sources

      September 26, 2025

      PostgreSQL 18 adds asynchronous I/O to improve performance

      September 26, 2025

      Distribution Release: Neptune 9.0

      September 25, 2025

      Distribution Release: Kali Linux 2025.3

      September 23, 2025

      Distribution Release: SysLinuxOS 13

      September 23, 2025

      Development Release: MX Linux 25 Beta 1

      September 22, 2025
    • Development
      1. Algorithms & Data Structures
      2. Artificial Intelligence
      3. Back-End Development
      4. Databases
      5. Front-End Development
      6. Libraries & Frameworks
      7. Machine Learning
      8. Security
      9. Software Engineering
      10. Tools & IDEs
      11. Web Design
      12. Web Development
      13. Web Security
      14. Programming Languages
        • PHP
        • JavaScript
      Featured

      PHP 8.5.0 RC 1 available for testing

      September 26, 2025
      Recent

      PHP 8.5.0 RC 1 available for testing

      September 26, 2025

      Terraform Code Generator Using Ollama and CodeGemma

      September 26, 2025

      Beyond Denial: How AI Concierge Services Can Transform Healthcare from Reactive to Proactive

      September 25, 2025
    • Operating Systems
      1. Windows
      2. Linux
      3. macOS
      Featured

      Distribution Release: Neptune 9.0

      September 25, 2025
      Recent

      Distribution Release: Neptune 9.0

      September 25, 2025

      FOSS Weekly #25.39: Kill Switch Phones, LMDE 7, Zorin OS 18 Beta, Polybar, Apt History and More Linux Stuff

      September 25, 2025

      Distribution Release: Kali Linux 2025.3

      September 23, 2025
    • Learning Resources
      • Books
      • Cheatsheets
      • Tutorials & Guides
    Home»Development»Routing and Multi-Screen Development in Flutter – a Beginner’s Guide

    Routing and Multi-Screen Development in Flutter – a Beginner’s Guide

    June 26, 2025

    Modern mobile applications are far from static, single-view experiences. Instead, they are dynamic, multi-faceted environments where users seamlessly transition between different features, content, and functionalities. Because of this inherent complexity, you’ll need to set up robust routing as well as a well-designed multi-screen architecture.

    In this tutorial, you’ll learn about Flutter’s fundamental navigation systems: Imperative Navigation (Navigator.push/pop) and Named Routes. We’ll explore their practical implementation through building an example Car List app. Through this process, you’ll learn how to navigate between a list of cars and their detailed views, and how to pass data between screens.

    By the end, you’ll gain a solid understanding of how to manage navigation stacks and create a smooth user experience in your Flutter applications.

    Table of Contents

    • Prerequisites

    • Why Should You Build Multi-Screen Apps?

    • Flutter’s Navigation Systems

    • The Simple Navigator API: Navigator.push

    • Named Routes: The Scalable Approach

    • Backstack Management: Controlling User Flow

    • Code Organization Tips for Scalable Navigation

    • Scalable Navigation: When Built-in Isn’t Enough

    • How to Set Up Your Flutter Project: The Car List App

    • Conclusion

    Prerequisites

    To get the most out of this tutorial, you should have:

    • Basic understanding of the Dart programming language: Familiarity with concepts like variables, data types, functions, classes, and asynchronous programming.

    • Fundamental knowledge of Flutter widgets: Knowing how to use StatelessWidget, StatefulWidget, and basic layout widgets like Column, Row, Container, and Text.

    • Flutter SDK installed and configured: Ensure you have a working Flutter development environment set up on your machine.

    • A code editor: Visual Studio Code or Android Studio with Flutter and Dart plugins installed.

    Why Should You Build Multi-Screen Apps?

    Real-world apps are rarely single-screen. Imagine a banking app that only shows your balance, or a social media app that only displays your feed. It’s simply not practical.

    Users expect to be able to:

    • View a list of items (for example, cars, products, news articles).

    • Tap on an item to see its detailed information.

    • Access user profiles, settings, or shopping carts.

    • Complete multi-step processes like checkout or onboarding.

    This intricate dance between different views highlights that navigation is a core user experience component. A fluid, intuitive, and predictable navigation flow directly translates to improved user satisfaction and maintainability for developers. Confusing navigation, on the other hand, can quickly lead to user frustration and abandonment.

    Flutter’s Navigation Systems

    Flutter provides powerful and flexible navigation mechanisms, catering to various application complexities. At a high level, we can categorize these mechanisms in the following ways:

    1. Imperative Navigation (Navigator.push / pop): This is the most basic and direct way to control the navigation stack. You explicitly tell the Navigator to push a new route or pop the current one.

    2. Named Routes: A more structured approach where routes are identified by string names, allowing for centralized configuration.

    3. onGenerateRoute / onUnknownRoute: Advanced callbacks within MaterialApp or WidgetsApp that provide fine-grained control over how routes are generated, especially useful for dynamic or deep linking scenarios.

    4. Declarative Navigation (for example, go_router, Beamer): For highly complex apps with deep linking, nested navigation, and web support, declarative packages offer a more state-driven approach to routing, where the URL or app state defines the current screen.

    For the purpose of this article, we will focus on the built-in Imperative Navigation and the more scalable Named Routes, illustrating them with the Car List App example. Let’s see how they work.

    The Simple Navigator API: Navigator.push

    The most straightforward way to navigate in Flutter is using Navigator.push. This method takes a MaterialPageRoute (or a CupertinoPageRoute for iOS-style transitions) that defines the widget for the new screen.

    Navigator.push(
      context,
      MaterialPageRoute(builder: (context) => DetailsScreen()),
    );
    

    Characteristics:

    • Best for smaller apps: Where the number of screens is limited and data passing is simple.

    • Can pass data using constructor: You can directly pass data to the new screen’s constructor (for example, DetailsScreen(car: myCar)). This is intuitive for simple data.

    While easy to use, Navigator.push can become cumbersome for larger apps as it requires direct instantiation of widgets at every navigation point, making centralized route management difficult.

    Named Routes: The Scalable Approach

    For applications with multiple screens and a more defined navigation structure, named routes offer a cleaner and more scalable solution. With named routes, you define a map of string names to screen-building functions within your MaterialApp.

    Our Car List App perfectly demonstrates this:

    <span class="hljs-comment">// In MyApp widget's build method</span>
    MaterialApp(
      initialRoute: <span class="hljs-string">'/'</span>, <span class="hljs-comment">// The starting screen of our app</span>
      routes: {
        <span class="hljs-string">'/'</span>: (context) => HomeScreen(),          <span class="hljs-comment">// Maps '/' to HomeScreen</span>
        <span class="hljs-string">'/details'</span>: (context) => DetailsScreen(), <span class="hljs-comment">// Maps '/details' to DetailsScreen</span>
        <span class="hljs-string">'/profile'</span>: (context) => ProfileScreen(), <span class="hljs-comment">// Maps '/profile' to ProfileScreen</span>
      },
    );
    

    To navigate using a named route, you use Navigator.pushNamed():

    <span class="hljs-comment">// From HomeScreen to DetailsScreen</span>
    Navigator.pushNamed(context, <span class="hljs-string">'/details'</span>);
    
    <span class="hljs-comment">// From HomeScreen to ProfileScreen</span>
    Navigator.pushNamed(context, <span class="hljs-string">'/profile'</span>);
    

    Advantages of named routes:

    • More scalable: As your app grows, managing routes by name is far easier than scattering MaterialPageRoute instantiations throughout your codebase.

    • Easy to centralize route management: All your app’s main navigation paths are defined in one clear location (the routes map).

    • Improved readability: Route names provide semantic meaning to your navigation actions.

    Passing and Receiving Data with Named Routes

    A common requirement for multi-screen apps is passing data from one screen to the next (for example, a selected car object from the list to its detail view). With named routes, the arguments property of Navigator.pushNamed is the idiomatic way to do this.

    When navigating:

    <span class="hljs-comment">// From HomeScreen, passing the 'car' object to the DetailsScreen</span>
    Navigator.pushNamed(context, <span class="hljs-string">'/details'</span>, arguments: car);
    

    On the receiving screen, ModalRoute.of(context)!.settings.arguments is used to retrieve the passed data. Remember to cast it to the expected type and handle nullability.

    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DetailsScreen</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{
      <span class="hljs-meta">@override</span>
      Widget build(BuildContext context) {
        <span class="hljs-comment">// Retrieve the Car object passed as arguments</span>
        <span class="hljs-keyword">final</span> Car car = ModalRoute.of(context)!.settings.arguments <span class="hljs-keyword">as</span> Car;
    
        <span class="hljs-keyword">return</span> Scaffold(
          appBar: AppBar(title: Text(car.name)),
          <span class="hljs-comment">// ... rest of the UI using 'car' data</span>
        );
      }
    }
    

    This pattern ensures type safety (with the as Car cast) and allows any data type to be passed, from simple strings to complex custom objects.

    Backstack Management: Controlling User Flow

    The Navigator manages a stack of routes. When you push a new route, it’s added to the top. When you go back, the top route is popped off the stack. Understanding and controlling this backstack is crucial for a smooth user experience.

    • Navigator.pop(context): This is the most common way to return to the previous screen. It removes the topmost route from the navigation stack. In our app, both DetailsScreen and ProfileScreen use this to return to HomeScreen.

        <span class="hljs-comment">// In DetailsScreen or ProfileScreen</span>
        ElevatedButton.icon(
          onPressed: () => Navigator.pop(context), <span class="hljs-comment">// Go back to the previous screen</span>
          icon: Icon(Icons.arrow_back),
          label: Text(<span class="hljs-string">'Back'</span>),
        )
      
    • Navigator.pushReplacementNamed(context, '/newRouteName'): Use this if you don’t want the user to go back to the current screen. It replaces the current route on the stack with the new one. This is ideal for scenarios like a login screen, where after successful login, you don’t want the user to be able to go back to the login page using the back button.

    • Navigator.pushNamedAndRemoveUntil(context, '/newRouteName', (route) => false): This powerful method pushes a new route and then removes all the previous routes until the predicate function returns true. If the predicate always returns false (as shown), it clears the entire stack and makes the new route the only one. This is perfect for login flows, onboarding, or splash screens where, once completed, the user should not be able to return to those initial screens.

    Code Organization Tips for Scalable Navigation

    As your app grows, maintaining a clear structure for your multi-screen components becomes vital. Here are some tips to help you keep things organized.

    1. Organize by feature: Instead of dumping all screens into one folder, group files related to a specific feature. For example:

    • lib/features/home/home_screen.dart

    • lib/features/home/widgets/

    • lib/features/details/details_screen.dart

    • lib/features/profile/profile_screen.dart

    2. Use dedicated folders for UI components:

    • lib/widgets/ (for reusable UI widgets across features)

    • lib/screens/ (for top-level screen widgets, or within feature folders)

    3. Abstract navigation logic: For bigger apps, consider creating a separate file (for example, lib/utils/app_routes.dart) to hold all your named route constants and potentially even methods for simplified navigation, rather than hardcoding string literals.

    Scalable Navigation: When Built-in Isn’t Enough

    While named routes are excellent for many applications, very large or complex apps with deep nested navigation, dynamic route generation, or specific web-based routing needs might benefit from third-party packages that offer a declarative navigation approach.

    Consider packages like:

    • go_router: A Google-supported package that focuses on declarative routing, deep linking, and web-friendly URLs. It maps application state to URLs, providing a powerful and flexible system.

    • auto_route: This package uses code generation to automatically create routing boilerplate, reducing manual effort and potential errors for complex navigation graphs.

    These solutions provide higher-level abstractions and solve common headaches associated with scaling navigation in large applications.

    Understanding the Car List App Example

    In this tutorial, we will be building a simple Car List App to illustrate the different navigation methods. This application will consist of these primary screens:

    1. Car List Screen: This screen will display a list of cars, each with basic information like its name and year. Users will be able to tap on a car in this list.

    2. Car Detail Screen: When a user taps on a car from the list, they will be navigated to this screen, which will display more detailed information about the selected car.

    3. Profile Screen: When a user taps on the floating action button with the person icon, they will be navigated to the profile screen

    This straightforward example will allow us to clearly demonstrate how to navigate between screens, pass data from one screen to another, and manage the navigation stack using Flutter’s built-in navigation systems.

    Now let’s get into our Car List App project so you can really see how this all works.

    How to Set Up Your Flutter Project: The Car List App

    To create this project, you’ll first need Flutter installed and configured on your system. If you haven’t already, ensure you have the Flutter SDK and a suitable IDE (like VS Code or Android Studio) set up.

    Step 1: Create a New Flutter Project

    Open your terminal or command prompt and run the following command to create a new Flutter project:

    flutter create car_list_app
    

    This command creates a new directory named car_list_app with a basic Flutter project structure inside it.

    Step 2: Organize the Project Structure

    Navigate into your new car_list_app directory (cd car_list_app). Inside the lib folder, you’ll initially find main.dart. We’re going to enhance this structure to better organize our code.

    Here’s the recommended directory structure for your project:

    car_list_app/
    ├── lib/
    │   ├── main.dart
    │   ├── models/
    │   │   └── car.dart
    │   ├── data/
    │   │   └── dummy_data.dart
    │   ├── screens/
    │   │   ├── home_screen.dart
    │   │   ├── details_screen.dart
    │   │   └── profile_screen.dart
    │   └── widgets/
    │       └── car_list_tile.dart (Optional, <span class="hljs-keyword">for</span> more complex list items)
    ├── pubspec.yaml
    ├── ... (other Flutter project files)
    

    Now, let’s populate these files with your provided code.

    Step 3: Populate the Files

    1. lib/models/car.dart

    This file will contain your Car data model.

    <span class="hljs-comment">// lib/models/car.dart</span>
    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Car</span> </span>{
      <span class="hljs-keyword">final</span> <span class="hljs-built_in">String</span> id;
      <span class="hljs-keyword">final</span> <span class="hljs-built_in">String</span> name;
      <span class="hljs-keyword">final</span> <span class="hljs-built_in">String</span> imageUrl;
      <span class="hljs-keyword">final</span> <span class="hljs-built_in">String</span> description;
    
      Car({
        <span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.id,
        <span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.name,
        <span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.imageUrl,
        <span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.description,
      });
    }
    

    2. lib/data/dummy_data.dart

    This file will hold your static car data list. In a real application, this data would likely come from an API or database.

    <span class="hljs-comment">// lib/data/dummy_data.dart</span>
    <span class="hljs-keyword">import</span> <span class="hljs-string">'../models/car.dart'</span>;
    
    <span class="hljs-keyword">final</span> <span class="hljs-built_in">List</span><Car> carList = [
      Car(
        id: <span class="hljs-string">'1'</span>,
        name: <span class="hljs-string">'Tesla Model S'</span>,
        imageUrl: <span class="hljs-string">'https://hips.hearstapps.com/hmg-prod/images/2025-tesla-model-s-2-672d42e16475f.jpg?crop=0.503xw:0.502xh;0.262xw,0.289xh&resize=980:*'</span>,
        description: <span class="hljs-string">'Electric car with autopilot features.'</span>,
      ),
      Car(
        id: <span class="hljs-string">'2'</span>,
        name: <span class="hljs-string">'BMW M4'</span>,
        imageUrl: <span class="hljs-string">'https://upload.wikimedia.org/wikipedia/commons/thumb/e/e2/2021_BMW_M4_Competition_Automatic_3.0_Front.jpg/1200px-2021_BMW_M4_Competition_Automatic_3.0_Front.jpg'</span>,
        description: <span class="hljs-string">'Sporty and powerful coupe.'</span>,
      ),
      Car(
        id: <span class="hljs-string">'3'</span>,
        name: <span class="hljs-string">'Ford Mustang'</span>,
        imageUrl: <span class="hljs-string">'https://images.prismic.io/carwow/c2d2e740-99e2-4faf-8cfa-b5a75c5037c0_ford-mustang-2024-lhd-front34static.jpg?auto=format&cs=tinysrgb&fit=max&q=60'</span>,
        description: <span class="hljs-string">'Iconic American muscle car.'</span>,
      ),
    ];
    

    3. lib/screens/home_screen.dart

    This file will contain the HomeScreen widget. Notice that the imports now point to our new file locations.

    <span class="hljs-comment">// lib/screens/home_screen.dart</span>
    <span class="hljs-keyword">import</span> <span class="hljs-string">'package:flutter/material.dart'</span>;
    <span class="hljs-keyword">import</span> <span class="hljs-string">'../data/dummy_data.dart'</span>; <span class="hljs-comment">// Import dummy data</span>
    <span class="hljs-keyword">import</span> <span class="hljs-string">'../models/car.dart'</span>;    <span class="hljs-comment">// Import Car model</span>
    
    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">HomeScreen</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{
      <span class="hljs-meta">@override</span>
      Widget build(BuildContext context) {
        <span class="hljs-keyword">return</span> Scaffold(
          appBar: AppBar(title: <span class="hljs-keyword">const</span> Text(<span class="hljs-string">'Available Cars'</span>)),
          body: ListView.builder(
            itemCount: carList.length,
            itemBuilder: (context, index) {
              <span class="hljs-keyword">final</span> car = carList[index];
              <span class="hljs-keyword">return</span> Card(
                margin: <span class="hljs-keyword">const</span> EdgeInsets.all(<span class="hljs-number">8</span>),
                child: ListTile(
                  contentPadding: <span class="hljs-keyword">const</span> EdgeInsets.all(<span class="hljs-number">10</span>),
                  leading: CircleAvatar(
                    radius: <span class="hljs-number">40</span>,
                    backgroundImage: NetworkImage(car.imageUrl),
                  ),
                  title: Text(car.name, style: <span class="hljs-keyword">const</span> TextStyle(fontWeight: FontWeight.bold)),
                  subtitle: Text(car.description, maxLines: <span class="hljs-number">2</span>, overflow: TextOverflow.ellipsis),
                  onTap: () {
                    Navigator.pushNamed(
                      context,
                      <span class="hljs-string">'/details'</span>,
                      arguments: car,
                    );
                  },
                ),
              );
            },
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: () => Navigator.pushNamed(context, <span class="hljs-string">'/profile'</span>),
            child: <span class="hljs-keyword">const</span> Icon(Icons.person),
            tooltip: <span class="hljs-string">'Go to Profile'</span>,
          ),
        );
      }
    }
    

    4. lib/screens/details_screen.dart

    This file will hold the DetailsScreen widget.

    <span class="hljs-comment">// lib/screens/details_screen.dart</span>
    <span class="hljs-keyword">import</span> <span class="hljs-string">'package:flutter/material.dart'</span>;
    <span class="hljs-keyword">import</span> <span class="hljs-string">'../models/car.dart'</span>; <span class="hljs-comment">// Import Car model</span>
    
    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DetailsScreen</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{
      <span class="hljs-meta">@override</span>
      Widget build(BuildContext context) {
        <span class="hljs-keyword">final</span> Car car = ModalRoute.of(context)!.settings.arguments <span class="hljs-keyword">as</span> Car;
    
        <span class="hljs-keyword">return</span> Scaffold(
          appBar: AppBar(title: Text(car.name)),
          body: Center(
            child: SingleChildScrollView(
              padding: <span class="hljs-keyword">const</span> EdgeInsets.all(<span class="hljs-number">16.0</span>),
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  ClipRRect(
                    borderRadius: BorderRadius.circular(<span class="hljs-number">20</span>),
                    child: Image.network(
                      car.imageUrl,
                      width: <span class="hljs-number">250</span>,
                      height: <span class="hljs-number">250</span>,
                      fit: BoxFit.cover,
                    ),
                  ),
                  <span class="hljs-keyword">const</span> SizedBox(height: <span class="hljs-number">24</span>),
                  Text(
                    car.name,
                    style: <span class="hljs-keyword">const</span> TextStyle(fontSize: <span class="hljs-number">26</span>, fontWeight: FontWeight.bold),
                    textAlign: TextAlign.center,
                  ),
                  <span class="hljs-keyword">const</span> SizedBox(height: <span class="hljs-number">12</span>),
                  Text(
                    car.description,
                    style: <span class="hljs-keyword">const</span> TextStyle(fontSize: <span class="hljs-number">16</span>),
                    textAlign: TextAlign.center,
                  ),
                  <span class="hljs-keyword">const</span> SizedBox(height: <span class="hljs-number">40</span>),
                  ElevatedButton.icon(
                    onPressed: () => Navigator.pop(context),
                    icon: <span class="hljs-keyword">const</span> Icon(Icons.arrow_back),
                    label: <span class="hljs-keyword">const</span> Text(<span class="hljs-string">'Back'</span>),
                  ),
                ],
              ),
            ),
          ),
        );
      }
    }
    

    5. lib/screens/profile_screen.dart

    This file will contain the ProfileScreen widget.

    <span class="hljs-comment">// lib/screens/profile_screen.dart</span>
    <span class="hljs-keyword">import</span> <span class="hljs-string">'package:flutter/material.dart'</span>;
    
    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ProfileScreen</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{
      <span class="hljs-keyword">final</span> <span class="hljs-built_in">String</span> profileImage = <span class="hljs-string">'https://www.shutterstock.com/image-vector/young-smiling-man-avatar-brown-600nw-2261401207.jpg'</span>;
    
      <span class="hljs-meta">@override</span>
      Widget build(BuildContext context) {
        <span class="hljs-keyword">return</span> Scaffold(
          appBar: AppBar(title: <span class="hljs-keyword">const</span> Text(<span class="hljs-string">'My Profile'</span>)),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center, <span class="hljs-comment">// Center content vertically</span>
              children: [
                CircleAvatar(
                  radius: <span class="hljs-number">60</span>,
                  backgroundImage: NetworkImage(profileImage),
                ),
                <span class="hljs-keyword">const</span> SizedBox(height: <span class="hljs-number">20</span>),
                <span class="hljs-keyword">const</span> Text(
                  <span class="hljs-string">'John Doe'</span>,
                  style: TextStyle(fontSize: <span class="hljs-number">22</span>, fontWeight: FontWeight.bold),
                ),
                Text(<span class="hljs-string">'john.doe@example.com'</span>, style: TextStyle(color: Colors.grey[<span class="hljs-number">600</span>])),
                <span class="hljs-keyword">const</span> SizedBox(height: <span class="hljs-number">30</span>),
                ElevatedButton.icon(
                  onPressed: () => Navigator.pop(context),
                  icon: <span class="hljs-keyword">const</span> Icon(Icons.arrow_back),
                  label: <span class="hljs-keyword">const</span> Text(<span class="hljs-string">'Back to Home'</span>),
                ),
              ],
            ),
          ),
        );
      }
    }
    

    6. lib/main.dart

    Finally, your main.dart will become much cleaner, and will mainly be responsible for running the app and defining the global routes.

    <span class="hljs-comment">// lib/main.dart</span>
    <span class="hljs-keyword">import</span> <span class="hljs-string">'package:flutter/material.dart'</span>;
    <span class="hljs-keyword">import</span> <span class="hljs-string">'screens/home_screen.dart'</span>;    <span class="hljs-comment">// Import HomeScreen</span>
    <span class="hljs-keyword">import</span> <span class="hljs-string">'screens/details_screen.dart'</span>; <span class="hljs-comment">// Import DetailsScreen</span>
    <span class="hljs-keyword">import</span> <span class="hljs-string">'screens/profile_screen.dart'</span>; <span class="hljs-comment">// Import ProfileScreen</span>
    
    <span class="hljs-keyword">void</span> main() => runApp(<span class="hljs-keyword">const</span> MyApp()); <span class="hljs-comment">// Add const for MyApp</span>
    
    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyApp</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{
      <span class="hljs-keyword">const</span> MyApp({<span class="hljs-keyword">super</span>.key}); <span class="hljs-comment">// Add const constructor</span>
    
      <span class="hljs-meta">@override</span>
      Widget build(BuildContext context) {
        <span class="hljs-keyword">return</span> MaterialApp(
          title: <span class="hljs-string">'Car List App'</span>,
          theme: ThemeData(primarySwatch: Colors.blue),
          initialRoute: <span class="hljs-string">'/'</span>,
          routes: {
            <span class="hljs-string">'/'</span>: (context) => <span class="hljs-keyword">const</span> HomeScreen(),      <span class="hljs-comment">// Add const to screen widgets</span>
            <span class="hljs-string">'/details'</span>: (context) => <span class="hljs-keyword">const</span> DetailsScreen(),
            <span class="hljs-string">'/profile'</span>: (context) => <span class="hljs-keyword">const</span> ProfileScreen(),
          },
        );
      }
    }
    

    Step 4: Run Your Application

    After structuring your project and placing the code in the respective files, you can run your application from the root of your car_list_app directory:

    flutter run
    

    This will launch the app on your connected device or emulator. You should see the list of cars, and be able to navigate to their details and the profile screen, demonstrating the clean multi-screen architecture and routing you’ve implemented.

    Screenshots

    home screen screenshot

    detail screen screenshot

    profile screen screenshot

    You can view the completed project here: https://github.com/Atuoha/routing_workshop

    Conclusion

    This organized structure significantly improves readability, reusability, and maintainability as your Flutter applications grow in complexity.

    Building effective multi-screen applications in Flutter hinges on a clear understanding and strategic implementation of its navigation systems. From the simplicity of Navigator.push to the scalability of named routes with Navigator.pushNamed and ModalRoute.of, Flutter offers robust tools for managing your app’s flow and passing essential data between screens.

    By thoughtfully organizing your code and leveraging the appropriate navigation strategy, you can create user-friendly, maintainable, and scalable Flutter applications that stand out in the crowded app marketplace.

    Source: freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More 

    Facebook Twitter Reddit Email Copy Link
    Previous ArticleWhy your AC isn’t blowing cold air – and 5 easy and quick ways to fix it
    Next Article Learn the Evolution of the Transformer Architecture Used in LLMs

    Related Posts

    Development

    PHP 8.5.0 RC 1 available for testing

    September 26, 2025
    Development

    Terraform Code Generator Using Ollama and CodeGemma

    September 26, 2025
    Leave A Reply Cancel Reply

    For security, use of Google's reCAPTCHA service is required which is subject to the Google Privacy Policy and Terms of Use.

    Continue Reading

    CVE-2025-6017 – Red Hat Advanced Cluster Management Information Disclosure Vulnerability

    Common Vulnerabilities and Exposures (CVEs)

    How to Fix Grounded 2 Crash on Startup (UE Augusta Fatal Error)

    Operating Systems

    CVE-2025-46265 – F5OS Improper Authorization Vulnerability

    Common Vulnerabilities and Exposures (CVEs)

    HOOK Android Trojan Adds Ransomware Overlays, Expands to 107 Remote Commands

    Development

    Highlights

    When hackers become hitmen

    July 1, 2025

    So, you think hacking is just about stealing information, extorting ransoms, or wiping out company…

    CVE-2024-54020 – Fortinet FortiManager Authorization Bypass

    May 28, 2025

    Forza Horizon 5 gets special Lamborghini livery celebrating Xbox and PlayStation players together

    May 13, 2025

    Windows 11 Preview Update KB5064080 Fixes Key File Explorer and Sharing Issues

    August 26, 2025
    © DevStackTips 2025. All rights reserved.
    • Contact
    • Privacy Policy

    Type above and press Enter to search. Press Esc to cancel.