我们应该使用Flutter不同的导航选项中的哪一个?

时间:2019-05-24 07:57:10

标签: flutter

背景

Flutter提供了两种不同的导航选项。

选项1.在MaterialPageRoute中使用Widget类。

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!'),
        ),
      ),
    );
  }
}

关键部分。

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

使用Navigator push方法,并将SecondRoute实例传递给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,
              // 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!'),
        ),
      ),
    );
  }
}

选项2。使用路线。

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!'),
        ),
      ),
    );
  }
}

关键部分。

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

还需要在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(),
    },
  ));
}

如果需要通过参数。

// 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.',
);

需要做一些额外的工作来获取参数。

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!'),
        ),
      ),
    );
  }
}

两个选项

  • 小部件
    • 简单易用。
    • 此小部件可用于导航或小部件树。
  • 路线
    • MaterialApp中的额外路线配置。
    • 进行额外的工作以从路线中检索参数。
    • 好像没有编译时间检查参数类型。
    • 由于没有路由参数,因此无法在小部件树中使用。

问题

  • 在生产就绪系统中,我们应该选择哪个选项。
  • 为什么要选择一个?

官方参考

  

Navigate to a new screen and back

     

Navigate with named routes

     

Pass arguments to a named route

1 个答案:

答案 0 :(得分:0)

我认为不应该同时使用其中之一,为什么不能同时使用两者,但这取决于项目结构和产品要求。

我通常执行以下操作:

  • 如果新屏幕取决于某些参数,任何参数,我将使用您的第一个选项,我非常喜欢在其构造函数(在本例中为小部件构造函数)中指定类的依赖关系。 / p>

  • 如果我已经有了一个具有依赖性的屏幕,那么我不会将命名路由与“未命名”路由混合使用。

  • 对于特殊的屏幕(例如选项卡导航中的根屏幕),它具有简单的导航(例如,关于我们的帮助,条款和条件),我通常会使用命名路线导航。

我认为,如果屏幕具有依赖项,那么您的第一个选择会更可靠,可以避免很多错误,并且可以进行类型检查,并且我认为它更易于扩展和维护。

第二个选项是用于简单导航。

因此,总而言之,我认为,如果框架提供了多种方法来做一件事情,那么您就不应该选择“ this AND the other”,通常最好选择“ this AND the another”,您应该考虑通常情况下,一种方法效果更好,而如果您发现另一种实现效果更好的情况,则不要害怕使用它。