Clean Navigation en Flutter Usando Generated Routes

Carlos Millan
26 junio, 2019

. . .

Traducción al español del artículo escrito por Dane Mackier, el cual puedes encontrar la versión en inglés aquí.

La navegación en Flutter se puede hacer de dos maneras. Named Routes, o Pushing Routes explícitamente al crear una instancia de PageRoute y pasarlo al navegador. Hacer push de rutas puede llegar a ser bastante explícito y compartir la lógica entre ellas se vuelve difícil. A la lógica le gusta comprobar si el usuario está autenticado para una vista específica. En esta publicación, configuraremos un Router para Flutter y le permitiremos usar rutas con nombre con parámetros.

Configuración

Crearemos dos vistas para jugar, puede agregarlas todas en el archivo main.dart.

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(home: Scaffold(body: Home()));
  }
}

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(child: Text('Home')),
    );
  }
}

class Feed extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(child: Text('Feed')),
    );
  }
}

Configurando Router / Routing

El MaterialApp le proporciona una propiedad llamada onGenerateRoutedonde puede pasar una función que devuelve un Route<dynamic> y toma en RouteSettings. Esto es lo que usaremos. Para mantener las cosas ordenadas, crearemos una clase Router. En él crearemos una función estática con la firma mencionada anteriormente. Crear un archivo router.dart.

class Router {
  Route<dynamic> generateRoute(RouteSettings settings) {
    
  }
}

La configuración contiene la información de ruta de la ruta solicitada. Nos proporciona dos cosas claves. El nombre y los argumentos. Usaremos el nombre para determinar qué vista devolver. Actualiza la función generate para que se vea así.

static Route<dynamic> generateRoute(RouteSettings settings) {
    switch (settings.name) {
      case '/':
        return MaterialPageRoute(builder: (_) => Home());
      case '/feed':
        return MaterialPageRoute(builder: (_) => Feed());
      default:
        return MaterialPageRoute(
            builder: (_) => Scaffold(
                  body: Center(
                      child: Text('No route defined for ${settings.name}')),
                ));
    }
  }

Lo que esto significa es que cuando el nombre es igual a ‘/’, entonces mostraremos el home. Cuando sea ‘/ feed’ mostraremos la vista de feed. Para evitar cometer errores en nuestro código, tomaremos estos valores codificados (valores mágicos) y los colocaremos en un archivo constants.dart que se puede usar en cualquier lugar.

/// This file contains all the routing constants used within the app

const String homeRoute = '/';
const String feedRoute = 'feed';

Actualice las sentencias de los cases de switch para usar las nuevas variables.

...
    switch (settings.name) {
      case homeRoute:
        return MaterialPageRoute(builder: (_) => Home());
      case feedRoute:
        return MaterialPageRoute(builder: (_) => Feed());
...

Ahora en su aplicación, donde define su MaterialApp, pasará la función generateRoute onGenerateRoute. Para definir la vista home como la vista de inicio, en lugar de configurar la propiedad de inicio en un widget, utilizaremos initialRoute en su lugar.

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
onGenerateRoute: Router.generateRoute,
initialRoute: homeRoute,
);
}
}

Navegación

Ahora cuando quieras navegar solo usarás

Navigator.pushNamed(context, feedRoute);

Esto te llevará a FeedView. Si queremos pasar parámetros a la vista Feed, eso es solo un pequeño cambio. Hagamos que nuestra vista de Feed tome un String como parámetro.

class Feed extends StatelessWidget {

  final String data;

  Feed(this.data);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(child: Text('Feed: $data')),
    );
  }
}

Agregue un floating action button en su homeView y onPressed hará push a la vista feed y pasaremos algunos datos string como un argumento.

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      floatingActionButton: FloatingActionButton(onPressed: (){
        Navigator.pushNamed(context, feedRoute, arguments: 'Data from home');
      },),
      body: Center(child: Text('Home')),
    );
  }
}

Ahora, en nuestro Router, tenemos que obtener estos datos pasados de la propiedad arguments en el settings y pasarlos a nuestro Feed.

case feedRoute:
    var data = settings.arguments as String;
    return MaterialPageRoute(builder: (_) => Feed(data));

Si hace tap en el floating action button en HomeView, navegará a feed y verá que los datos están allí. Puede pasar cualquier valor en los argumentos. Solo asegúrate de convertir al tipo que deseas y pásalo a tu vista. Objetos complejos, o incluso otros widgets.

15

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Comunidades en Español