Flutter – Widget heredado

Si eres un desarrollador de Flutter, entonces sabes lo fácil que es crear Flutter UI. Pero cuando tiene muchos widgets en su aplicación y quiere pasar datos de un widget a otro, esto será una molestia para muchos desarrolladores, especialmente para los novatos, les resultará muy difícil pasar los datos. un widget del árbol de widgets al widget inferior. Y si sabe acerca de los widgets, generalmente hay dos tipos de widgets sin estado y widgets con estado. Pero hay otro tipo de widget llamado InheritedWidget.

 

Widget heredado

El widget heredado nos brinda una forma conveniente de pasar datos entre widgets. Mientras desarrolla una aplicación, necesitará algunos datos de los widgets de sus padres o concederá widgets de padres o tal vez más allá de eso. Entonces, si su aplicación es pequeña, puede pasar sus datos usando el constructor de la clase de widget, pero para una aplicación más grande, esta no es una tarea fácil. Sin saberlo, hemos utilizado widgets heredados en muchos lugares mientras desarrollábamos la aplicación flutter.Theme.of(context), MediQuery.of(context) y Navigator.of(context) ( si revisa los códigos de Navigation, encontrará eso ).

Dart

const InheritedWidget({
Key? key, required Widget child
})
: super(key: key, child: child);

El primer parámetro es la clave, una clave es un identificador para widgets y elementos en Flutter. Un nuevo widget solo se utilizará para actualizar un widget existente si su clave es la misma que la clave del widget actual asociado con el elemento. El parámetro secundario es de tipo Widget, por lo que podemos pasar cualquier widget como parámetro como widget secundario. Vamos a crear un ejemplo simple,

Dart

import 'package:flutter/material.dart';
 
void main() => runApp(MyApp());
 
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
 
  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: MyScreen(),
    );
  }
}
 
class MyInheritedWidget extends InheritedWidget {
  const MyInheritedWidget({Key? key,required this.child,required this.message}) : super(key: key, child: child);
 
  final Widget child;
   
  // message of our inherited widget class
  final String message;
 
  static MyInheritedWidget of(BuildContext context) {
    return context.dependOnInheritedWidgetOfExactType<MyInheritedWidget>()!;
  }
 
  @override
  bool updateShouldNotify(MyInheritedWidget oldWidget) {
    return oldWidget.message != message;
  }
}
 
class MyScreen extends StatelessWidget {
  const MyScreen({Key? key}) : super(key: key);
 
    @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("GFG"),
        backgroundColor: Colors.green,
      ),
      body: MyInheritedWidget(
        // passing the message as string
        message:"Hey GEEKS",
        child: Builder(
          builder: (BuildContext innerContext) {
     
            return Center(
                        child: Text(
                     // using the message of our inherited widget using of()
                     MyInheritedWidget.of(innerContext).message,
                      style: const TextStyle(fontWeight: FontWeight.bold),
                )
              );
          },
        ),
      ),
    );
  }
}

Producción:

Output

 

La clase de widget heredada es inmutable. Aquí hemos creado una variable String llamada mensaje y se declara como final para que no podamos modificarla en el futuro. Anulamos un método llamado updateShouldNotify que tiene un widget antiguo de parámetro, este método se usa para notificar al widget cuando lo reconstruimos. Por ejemplo, si los datos que contiene este widget son los mismos que los que contiene el widget antiguo, entonces no necesitamos reconstruir los widgets y no necesitamos notificar al widget. Pero la parte importante es la estática de(), ¿es obligatorio definirla en nuestro widget heredado? La respuesta es no. Pero esta es una convención que seguimos, puede llamar directamente a context.dependOnInheritedWidgetOfExactType<MyInheritedWidget>() y usar eso.

Pocos desarrolladores definen el widget heredado como privado y lo implementan en otra clase, no hay una forma estándar de definir un widget heredado, pero si observa los códigos Theme.of (contexto), verá que usó una clase privada InheritedWidget.

Nota: Vea que estamos usando Builder() e innerContext para acceder al mensaje del widget heredado, si usa el contexto, entonces no funcionará. Flutter dice que cuando usamos el método, el contexto debe ser un descendiente de InheritedWidget, lo que significa que el contexto debe estar debajo del inheridWidget en el árbol.

El ejemplo anterior es un ejemplo simple, hagamos un ejemplo complicado,

Dart

import 'package:flutter/material.dart';
 
void main() => runApp(MyApp());
 
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyNavigation(),
    );
  }
}
 
// route function for  Routing of pages
Route generatePage(child) {
  return MaterialPageRoute(builder: (context) => child);
}
 
class MyNavigation extends StatelessWidget {
  const MyNavigation({Key? key}) : super(key: key);
 
  @override
  Widget build(BuildContext context) {
    return MyInheritedWidget(
      // message as string for our inherited widget
      message: 'Hey, Geekss',
      child: Navigator(
        onGenerateRoute: (settings) {
          switch (settings.name) {
            case 'screen1':
              // Route for firs screen
              return generatePage(const FirstScreen());
            case 'screen2':
              // Route for second screen
              return generatePage(const SecondScreen());
           
          }
        },
        // our first screen in app
        initialRoute: 'screen1',
      ),
    );
  }
}
 
class MyInheritedWidget extends InheritedWidget {
  const MyInheritedWidget({Key? key,required this.child,required this.message}) : super(key: key, child: child);
 
  @override
  final Widget child;
   
  // message variable for
  // our inherited widget
  final String message;
 
  static MyInheritedWidget of(BuildContext context) {
    return context.dependOnInheritedWidgetOfExactType<MyInheritedWidget>()!;
  }
 
  @override
  bool updateShouldNotify(MyInheritedWidget oldWidget) {
    return true;
  }
}
 
class FirstScreen extends StatelessWidget {
  const FirstScreen({Key? key}) : super(key: key);
 
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Geeks For Geeks'),
        backgroundColor: Colors.green,
      ),
   
      body: Center(
        child: ElevatedButton(
          // showing message variable of our
          // inherotedd widget class using of()
          child: Text(MyInheritedWidget.of(context).message),
          onPressed: () {
            Navigator.of(context)
                   // navigate to second screen
                .push(MaterialPageRoute(builder: (_) => SecondScreen()));
          },
        ),
      ),
    );
  }
}
 
class SecondScreen extends StatelessWidget {
  const SecondScreen({Key? key}) : super(key: key);
 
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Geeks For Geeks'),
        backgroundColor: Colors.green,
      ),
      body: Center(
        child: Text(MyInheritedWidget.of(context).message + "\n This is second screen",style: const TextStyle(fontWeight: FontWeight.bold),),
        // showing message variable of our
        // inherotedd widget class using of()
      )
    );
  }
}

Salida final:

Explicación:

En el ejemplo anterior, solo creamos dos pantallas y usamos la navegación. Si verifica el código correctamente, verá que creamos un widget de navegación como elemento secundario de MyInheritedWidget. Usamos la variable de mensaje de MyInheritedWidget en ambas pantallas. Si no creamos un widget de navegación como elemento secundario de MyInheritedWidget, no podremos acceder a la variable de mensaje de MyInheritedWidget. Podemos usar InheritedWidget como una herramienta de administración de estado, pero la complejidad aumentará, por lo que el equipo de flutter recomienda que, para una aplicación compleja y grande, deberíamos usar alguna herramienta de administración de estado.

Publicación traducida automáticamente

Artículo escrito por niranjannaik y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

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