¿Qué es un `InheritedWidget` y por qué es importante para la gestión de estado?
Ver respuesta — intenta responderla en voz alta primero
Un InheritedWidget es un widget especial que propaga datos hacia abajo en el árbol de forma eficiente, para que cualquier widget descendiente pueda leerlos con .of(context) sin pasarlos manualmente por cada constructor. Es la base sobre la que están construidos Theme, MediaQuery, Provider y muchas soluciones de estado.
Imagina que un dato (el tema, el usuario logueado) lo necesitan widgets muy profundos en el árbol. Pasarlo por parámetro en cada nivel es tedioso y frágil (eso se llama prop drilling).
Un InheritedWidget lo resuelve: lo colocas alto en el árbol y cualquier descendiente accede a él con DatosDeApp.of(context). Cuando el InheritedWidget cambia, Flutter reconstruye automáticamente solo los widgets que dependen de él (los que llamaron a .of(context)), no todo el árbol.
Por eso Theme.of(context) y MediaQuery.of(context) funcionan: por debajo son InheritedWidget. Casi nadie escribe uno a mano hoy en día; se usa Provider/Riverpod, que lo envuelven, pero entender esto es clave en entrevistas.
import 'package:flutter/material.dart';
// Un InheritedWidget que expone un color a sus descendientes
class ColorApp extends InheritedWidget {
final Color color;
const ColorApp({
super.key,
required this.color,
required super.child,
});
// El acceso típico: ColorApp.of(context)
static ColorApp of(BuildContext context) {
final resultado =
context.dependOnInheritedWidgetOfExactType<ColorApp>();
assert(resultado != null, 'No se encontró un ColorApp en el árbol');
return resultado!;
}
// Le dice a Flutter cuándo reconstruir a quienes dependen de él
@override
bool updateShouldNotify(ColorApp oldWidget) => color != oldWidget.color;
}
// Un descendiente que lee el color sin recibirlo por parámetro
class Cajita extends StatelessWidget {
const Cajita({super.key});
@override
Widget build(BuildContext context) {
final color = ColorApp.of(context).color;
return Container(width: 50, height: 50, color: color);
}
}
No implementar bien updateShouldNotify. Ese método decide si los widgets dependientes deben reconstruirse cuando el InheritedWidget cambia. Si siempre devuelves true, reconstruyes de más; si siempre devuelves false, la UI no reacciona a los cambios. Debe comparar el valor viejo con el nuevo.
"Un
InheritedWidgetpropaga datos hacia abajo en el árbol de forma eficiente, para que cualquier descendiente los lea con.of(context)en vez de pasarlos por parámetro en cada nivel. Cuando cambia, Flutter reconstruye solo los widgets que dependen de él. Es la base deTheme,MediaQueryy de soluciones como Provider. Rara vez escribo uno a mano, pero entenderlo me ayuda a saber cómo funcionan esas librerías por debajo. La pieza clave esupdateShouldNotify, que decide cuándo notificar a los dependientes."
¿Cómo hace Flutter para reconstruir solo los widgets que usan un InheritedWidget y no todo el árbol?
Ver respuesta
Cuando un widget llama a dependOnInheritedWidgetOfExactType (que es lo que hace .of(context) internamente), Flutter registra a ese widget como dependiente del InheritedWidget. Al cambiar, y si updateShouldNotify devuelve true, Flutter reconstruye únicamente los elementos registrados como dependientes, no el árbol completo. Por eso es eficiente.