Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which one we should go with Flutter different navigation options?

Tags:

flutter

Background

Flutter provides two different navigation options.

Option 1. Use Widget class in MaterialPageRoute.

class FirstRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('First Route'),
      ),
      body: Center(
        child: RaisedButton(
          child: Text('Open route'),
          onPressed: () {
            Navigator.push(
              context,
              MaterialPageRoute(builder: (context) => SecondRoute()),
            );
          },
        ),
      ),
    );
  }
}

class SecondRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Second Route"),
      ),
      body: Center(
        child: RaisedButton(
          onPressed: () {
            Navigator.pop(context);
          },
          child: Text('Go back!'),
        ),
      ),
    );
  }
}

The key part.

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

Use the Navigator push method and pass the SecondRoute instance to MaterialPageRoute contructor.

If need to pass the paramter.

class FirstRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('First Route'),
      ),
      body: Center(
        child: RaisedButton(
          child: Text('Open route'),
          onPressed: () {
            Navigator.push(
              context,
              // The parameter passed via SecondRoute constructor.
              MaterialPageRoute(builder: (context) => SecondRoute(message: 'The message for second view.')),
            );
          },
        ),
      ),
    );
  }
}

class SecondRoute extends StatelessWidget {
  // This is the parameter the SecondRoute needs.
  final String message;
  
  SecondRoute({@required this.message});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Second Route"),
      ),
      body: Center(
        child: RaisedButton(
          onPressed: () {
            Navigator.pop(context);
          },
          child: Text('Go back!'),
        ),
      ),
    );
  }
}

Option 2. Use route.

class FirstScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('First Screen'),
      ),
      body: Center(
        child: RaisedButton(
          child: Text('Launch screen'),
          onPressed: () {
            // Navigate to the second screen using a named route.
            Navigator.pushNamed(context, '/second');
          },
        ),
      ),
    );
  }
}

class SecondScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Second Screen"),
      ),
      body: Center(
        child: RaisedButton(
          onPressed: () {
            // Navigate back to the first screen by popping the current route
            // off the stack
            Navigator.pop(context);
          },
          child: Text('Go back!'),
        ),
      ),
    );
  }
}

The key part.

Navigator.pushNamed(context, '/second');

Also need to register the routes in MaterialApp.

void main() {
  runApp(MaterialApp(
    title: 'Named Routes Demo',
    // Start the app with the "/" named route. In our case, the app will start
    // on the FirstScreen Widget
    initialRoute: '/',
    routes: {
      // When we navigate to the "/" route, build the FirstScreen Widget
      '/': (context) => FirstScreen(),
      // When we navigate to the "/second" route, build the SecondScreen Widget
      '/second': (context) => SecondScreen(),
    },
  ));
}

If need to pass the paramter.

// When the user taps the button, navigate to a named route
// and provide the arguments as an optional parameter.
Navigator.pushNamed(
  context,
  '/second',
  arguments: 'The message for second view.',
);

Need to do some extra work to get the parameter.

class SecondScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // Gets the parameter from the route. Any type of the parameter is allowed.
    final String message = ModalRoute.of(context).settings.arguments;
  
    return Scaffold(
      appBar: AppBar(
        title: Text("Second Screen"),
      ),
      body: Center(
        child: RaisedButton(
          onPressed: () {
            // Navigate back to the first screen by popping the current route
            // off the stack
            Navigator.pop(context);
          },
          child: Text('Go back!'),
        ),
      ),
    );
  }
}

The two options

  • Widget
    • Simple and easy to use.
    • This Widget can be used by navigation or Widget tree.
  • route
    • Extra routes config in MaterialApp.
    • Extra work to retrieve the parameter from the route.
    • Looks like there's no compile time check for parameter type.
    • Cannot be used in Widget tree since there will be no route parameter.

The question

  • From the production ready system we should go with which option.
  • Why choose one over the other?

Official References

Navigate to a new screen and back

Navigate with named routes

Pass arguments to a named route

like image 709
Hui Avatar asked Oct 22 '25 04:10

Hui


1 Answers

I think there shouldn't be use one or the other, why not both, but this depends on the project structure and the product requirements.

I usually do the following:

  • If the new screen depends on some parameters, any parameters, I will use your first option, I like a lot to specify the dependencies of a class in it's constructor, in this case, in the widget constructor.

  • If I already have a screen that has dependencies I will not mix named routes with "unnamed" routes.

  • For special screens, for example a root screen in a tab navigation, that has simple navigation (like, help, about us, T&C), I will usually use a named route navigation.

In my opinion, your first option is more reliable if the screen has dependencies, you'll avoid a lot of errors and you'll get the type check and I think it's easier to extend and maintain.

The second option, is for simple navigation.

So in conclusion, in my opinion, if the framework provides multiple ways of doing one thing, you shouldn't go with "this OR the other", usually it's best to go "this AND the other", you should think of common cases when one way works better and if you find cases where the other implementation works better, don't be afraid to use it, after all.

like image 176
danypata Avatar answered Oct 24 '25 20:10

danypata



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!