InheritedWidget — qué es, paso de datos en el árbol y cómo funciona

Autor: IT Sectr Publicado: 2026-07-02 Tiempo de lectura: 9 min

InheritedWidget es un widget especial en Flutter que pasa datos hacia abajo por el árbol de widgets sin pasarlos explícitamente a través de constructores. Los widgets hijos acceden a los datos mediante BuildContext y se suscriben automáticamente a las actualizaciones. Cuando los datos en InheritedWidget cambian, todos los widgets dependientes se reconstruyen. Según Flutter API Reference, 2025, InheritedWidget es la base de Theme, MediaQuery, Localizations y la mayoría de las bibliotecas de gestión de estado.

Puntos clave

  • InheritedWidget pasa datos hacia abajo por el Widget Tree sin tener que pasarlos explícitamente a través de cada widget.
  • Suscripción automática — los widgets que usan dependOnInheritedWidgetOfExactType se reconstruyen cuando los datos cambian.
  • Theme y MediaQuery son ejemplos incorporados de InheritedWidget, disponibles en cada aplicación Flutter.
  • Provider y Riverpod están construidos sobre InheritedWidget y amplían sus capacidades para la gestión de estado.
  • Implementación correcta requiere sobrescribir updateShouldNotify para evitar reconstrucciones innecesarias.

¿Qué es InheritedWidget en Flutter?

InheritedWidget es un widget que hace que sus datos estén disponibles para todos los descendientes en el Widget Tree. A diferencia de un widget normal que solo pasa datos a través de constructores a los elementos hijos, InheritedWidget permite que cualquier widget en el subárbol acceda a los datos sin una cadena de parámetros. Esto resuelve el problema de “prop drilling” — pasar datos a través de muchos widgets intermedios que no usan estos datos por sí mismos.

InheritedWidget incorporados

Flutter incluye varios InheritedWidget incorporados: Theme (esquema de colores y estilos), MediaQuery (tamaño de pantalla, orientación, densidad de píxeles), Localizations (cadenas localizadas), Directionality (dirección del texto), DefaultTextStyle (estilo de texto predeterminado). Estos widgets son establecidos por widgets raíz como MaterialApp y están disponibles en toda la aplicación.

Ciclo de vida de InheritedWidget

InheritedWidget no tiene estado propio — almacena los datos pasados a través del constructor. Cuando el padre de InheritedWidget se reconstruye con nuevos datos, se llama al método updateShouldNotify para comparar los datos antiguos y nuevos. Si el método devuelve true, todos los widgets dependientes se marcan para reconstrucción. Este es un mecanismo de actualización reactiva simple pero efectivo.

Cómo funciona el paso de datos a través de InheritedWidget

El mecanismo de paso de datos a través de InheritedWidget se basa en el Element Tree. Cuando un widget llama a dependOnInheritedWidgetOfExactType, el elemento correspondiente registra una dependencia en InheritedElement. Cuando InheritedWidget cambia, InheritedElement notifica a todos los elementos dependientes, que se reconstruyen en el siguiente fotograma.

Registro de dependencia

El método dependOnInheritedWidgetOfExactType no solo encuentra InheritedWidget en el árbol — suscribe el elemento actual a las notificaciones. Si usaras findAncestorWidgetOfExactType en lugar de dependOn, el widget obtendría los datos pero no se reconstruiría cuando cambien. Esta es una diferencia importante: dependOn es una suscripción, findAncestor es una búsqueda única.

Recorrido del árbol de InheritedWidget

Cuando un widget solicita un InheritedWidget, Flutter asciende por el Element Tree desde el elemento actual hasta la raíz, verificando cada InheritedElement para encontrar una coincidencia de tipo. Se devuelve el primer InheritedElement que coincide. Esto significa que el InheritedWidget más cercano en el árbol tiene prioridad — puedes sobrescribir datos en un nivel específico colocando InheritedWidget más cerca de los descendientes.

dart
class ThemeData {
  final Color primaryColor;
  final TextTheme textTheme;

  const ThemeData({required this.primaryColor, required this.textTheme});
}

class MyTheme extends InheritedWidget {
  final ThemeData data;

  const MyTheme({required this.data, required Widget child}) : super(child: child);

  static MyTheme of(BuildContext context) {
    final widget = context.dependOnInheritedWidgetOfExactType<MyTheme>();
    assert(widget != null, "MyTheme not found in tree");
    return widget!;
  }

  @override
  bool updateShouldNotify(MyTheme oldWidget) => oldWidget.data != data;
}

En este ejemplo, MyTheme usa un método estático of para proporcionar datos a los descendientes. El método dependOnInheritedWidgetOfExactType registra una dependencia, y updateShouldNotify compara los datos antiguos y nuevos para determinar si los widgets dependientes necesitan reconstruirse.

Crear un InheritedWidget personalizado

Crear un InheritedWidget personalizado consta de dos pasos: definir una clase que extienda InheritedWidget e implementar un método estático of para el acceso desde los descendientes. Los datos se pasan a través del constructor, y el método updateShouldNotify determina cuándo deben reconstruirse los widgets dependientes.

Paso 1: Definir la clase InheritedWidget

La clase debe extender InheritedWidget y aceptar datos a través de un constructor con un parámetro child obligatorio. Los datos pueden ser de cualquier tipo: primitivos, objetos, funciones. La regla principal es que los datos deben ser inmutables para poder comparar de forma fiable los valores antiguos y nuevos.

Paso 2: Método estático of

El método estático of toma BuildContext y devuelve los datos de InheritedWidget. Internamente, llama a dependOnInheritedWidgetOfExactType, que encuentra el InheritedWidget más cercano del tipo especificado en el árbol. Si no se encuentra InheritedWidget, el método lanza una excepción o devuelve un valor predeterminado según la implementación.

Paso 3: Uso en widgets

Para acceder a los datos, el widget llama a MyWidget.of(context) dentro del método build. Flutter suscribe automáticamente el widget a las actualizaciones. Si los datos cambian, el widget se reconstruye en el siguiente fotograma. Esto permite un código limpio y declarativo sin parámetros innecesarios.

dart
class UserPreferences extends InheritedWidget {
  final String languageCode;
  final bool darkMode;

  const UserPreferences({
    required this.languageCode,
    required this.darkMode,
    required Widget child,
  }) : super(child: child);

  static UserPreferences of(BuildContext context) {
    return context.dependOnInheritedWidgetOfExactType<UserPreferences>()!;
  }

  @override
  bool updateShouldNotify(UserPreferences oldWidget) =>
    oldWidget.languageCode != languageCode || oldWidget.darkMode != darkMode;
}

En este ejemplo, UserPreferences almacena la configuración del usuario. El método updateShouldNotify compara cada campo individualmente, lo que evita reconstrucciones innecesarias cuando solo cambia un parámetro. Usa un enfoque similar para tus propios InheritedWidget con múltiples campos.

El método updateShouldNotify y la prevención de reconstrucciones innecesarias

updateShouldNotify es el método clave de InheritedWidget que determina si es necesario notificar a los widgets dependientes sobre cambios en los datos. Si el método devuelve false, los widgets dependientes no se reconstruyen, incluso si el propio InheritedWidget recibió una nueva instancia con los mismos datos. Esto es críticamente importante para el rendimiento.

Implementación correcta de updateShouldNotify

Compara solo aquellos campos que realmente han cambiado y afectan la visualización. Si InheritedWidget contiene 10 campos pero solo uno afecta la UI, verifica solo ese campo. Para colecciones, usa comparación profunda o estructuras de datos inmutables. No uses == para List o Map, ya que comparan por referencia.

  • Primitivos — usa comparaciones directas: oldWidget.value != value.
  • Objetos inmutables — usa == sobrescrito: oldWidget.data != data (si data sobrescribe ==).
  • Colecciones — usa listEquals, mapEquals de package:flutter/foundation.dart.

Errores en la implementación de updateShouldNotify

El error más común es devolver true sin comparación. Esto hace que todos los widgets dependientes se reconstruyan en cada actualización del padre, incluso si los datos no han cambiado. El segundo error es devolver false cuando los datos han cambiado, lo que lleva a una UI desactualizada. El tercero es una comparación compleja que se ejecuta cada fotograma y ralentiza el rendimiento.

InheritedWidget vs callbacks: ¿cuál elegir?

InheritedWidget y los callbacks (pasar funciones a través de constructores) resuelven diferentes problemas. InheritedWidget es adecuado para datos que necesitan muchos widgets en diferentes niveles del árbol. Los callbacks son convenientes para el paso unidireccional de eventos del padre a un hijo específico o viceversa. La elección depende de la arquitectura de la aplicación y la frecuencia de las actualizaciones.

Cuándo usar InheritedWidget

Usa InheritedWidget cuando los datos sean necesarios para muchos widgets en diferentes niveles de anidamiento: tema de la aplicación, configuración del usuario, información del dispositivo, datos de la sesión actual. InheritedWidget es especialmente efectivo para datos “globales” que rara vez cambian pero se necesitan en diferentes partes de la UI.

Cuándo usar callbacks

Los callbacks (funciones de devolución de llamada) son adecuados para pasar eventos de un widget hijo a un padre: pulsación de botón, selección de elemento de lista, envío de formulario. Los callbacks indican explícitamente qué acciones puede realizar un hijo y no crean dependencias ocultas. Para pasar datos hacia abajo por el árbol en un número reducido de niveles, también es más simple usar parámetros del constructor.

CriterioInheritedWidgetCallbacks
DirecciónDe arriba abajo (padre → descendientes)De abajo arriba (hijo → padre) o directa
ÁmbitoTodo el subárbolWidget específico
ReconstrucciónAutomática al cambiar datosRequiere setState manual
ComplejidadMedia (requiere clase InheritedWidget)Baja (solo una función)

InheritedWidget y las bibliotecas de gestión de estado

Provider y Riverpod son bibliotecas populares de gestión de estado en Flutter construidas sobre InheritedWidget. Amplían sus capacidades: añaden soporte para ChangeNotifier, eliminación automática al desmontar, inicialización diferida y sintaxis simplificada con genéricos.

Provider basado en InheritedWidget

Provider usa InheritedWidget para pasar un objeto de cualquier tipo hacia abajo por el árbol. ChangeNotifierProvider rastrea los cambios a través de ChangeNotifier y llama a updateShouldNotify cuando se invoca notifyListeners. Esto libera al desarrollador de crear manualmente InheritedWidget e implementar updateShouldNotify.

Comparación con InheritedWidget directo

El InheritedWidget directo ofrece más control y no requiere dependencias externas. Provider proporciona infraestructura lista: Consumer, Selector, MultiProvider, ProxyProvider. La elección depende de la complejidad de la aplicación. Para proyectos simples, el InheritedWidget directo es suficiente; para grandes, Provider o Riverpod reducen el código repetitivo.

dart
// InheritedWidget directo
class UserProvider extends InheritedWidget {
  final UserData userData;
  const UserProvider({required this.userData, required Widget child}) : super(child: child);
  static UserData of(BuildContext context) => context.dependOnInheritedWidgetOfExactType<UserProvider>()!.userData;
  @override
  bool updateShouldNotify(UserProvider old) => old.userData != userData;
}

// Equivalente de Provider
return ChangeNotifierProvider<UserData>(
  create: (_) => UserData(),
  child: MyApp(),
);

Ambos enfoques en el ejemplo resuelven el mismo problema — pasar UserData hacia abajo por el árbol. Provider reduce el volumen de código pero oculta la mecánica de InheritedWidget. El InheritedWidget directo ofrece control total y comprensión de lo que sucede, lo que es especialmente importante al aprender Flutter y depurar problemas complejos de reconstrucción.

Preguntas frecuentes

¿En qué se diferencia InheritedWidget de un widget normal?

InheritedWidget hace que los datos estén disponibles para todos los descendientes a través de BuildContext, mientras que un widget normal solo pasa datos a través del constructor. InheritedWidget también suscribe a los descendientes a las actualizaciones de datos.

¿Con qué frecuencia se reconstruyen los widgets dependientes?

Los widgets dependientes solo se reconstruyen cuando updateShouldNotify devuelve true. Si el método se implementa correctamente, la reconstrucción solo ocurre cuando los datos realmente cambian, no en cada reconstrucción del padre.

¿Se pueden usar varios InheritedWidget en el mismo árbol?

Sí, puedes usar cualquier cantidad de InheritedWidget en el mismo árbol. Cada uno proporciona datos de un tipo específico, y los widgets pueden obtener datos de varios InheritedWidget simultáneamente.

¿Cuál es la diferencia entre dependOnInheritedWidgetOfExactType y findAncestorWidgetOfExactType?

dependOn suscribe el widget a las actualizaciones — cuando los datos cambian, el widget se reconstruye. findAncestor realiza una búsqueda única sin suscripción, y el widget no se enterará de los cambios en los datos.

¿Es InheritedWidget adecuado para la gestión de estado compleja?

Para estado simple (tema, configuración) InheritedWidget es suficiente. Para estado complejo con lógica de negocio, usa Provider, Riverpod o BLoC — están construidos sobre InheritedWidget y añaden la infraestructura necesaria.

Resumen

  • InheritedWidget es un widget especial de Flutter para pasar datos hacia abajo por el árbol con suscripción automática a las actualizaciones.
  • Mecanismo de funcionamiento basado en el Element Tree: InheritedElement registra elementos dependientes y les notifica los cambios.
  • updateShouldNotify — el método clave para evitar reconstrucciones innecesarias de widgets dependientes.
  • InheritedWidget incorporados: Theme, MediaQuery, Localizations, Directionality, DefaultTextStyle.
  • Crear uno personalizado incluye herencia de clase, paso de datos a través del constructor y un método estático of.
  • Provider y Riverpod están construidos sobre InheritedWidget y añaden ChangeNotifier, Consumer, Selector y sintaxis simplificada.
  • InheritedWidget resuelve el problema de prop drilling y es la base de la gestión de estado reactiva en Flutter.

Desarrollaremos una aplicación móvil llave en mano

IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.

Discutir el proyecto

Lea también