¿Cuál es la forma correcta de utilizar un InheritedWidget? Hasta ahora entendí que te da la oportunidad de propagar datos por el árbol de widgets. En extremo, si pones como RootWidget, será accesible desde todos los Widgets en el árbol en todas las Rutas, lo cual está bien porque de alguna manera tengo que hacer que mi ViewModel / Model sea accesible para mis Widgets sin tener que recurrir a globales o Singletons.
PERO InheritedWidget es inmutable, entonces, ¿cómo puedo actualizarlo? Y lo que es más importante, ¿cómo se activan mis widgets con estado para reconstruir sus subárboles?
Desafortunadamente, la documentación aquí es muy poco clara y después de una discusión con muchos, nadie parece saber realmente cuál es la forma correcta de usarla.
Añado una cita de Brian Egan:
Sí, lo veo como una forma de propagar datos por el árbol. Lo que encuentro confuso, de los documentos de la API:
"Los widgets heredados, cuando se hace referencia a ellos de esta manera, harán que el consumidor reconstruya cuando el widget heredado cambie de estado".
Cuando leí esto por primera vez, pensé:
Podría meter algunos datos en el InheritedWidget y mutarlos más tarde. Cuando ocurra esa mutación, reconstruirá todos los Widgets que hacen referencia a mi InheritedWidget Lo que encontré:
Para mutar el estado de un InheritedWidget, debes envolverlo en un StatefulWidget. Luego, mutas el estado del StatefulWidget y pasas estos datos al InheritedWidget, que entrega los datos a todos sus hijos. Sin embargo, en ese caso, parece reconstruir todo el árbol debajo del StatefulWidget, no solo los Widgets que hacen referencia al InheritedWidget. ¿Es eso correcto? ¿O de alguna manera sabrá cómo omitir los widgets que hacen referencia al InheritedWidget si updateShouldNotify devuelve falso?
fuente
MyInherited.of(context)
.updateShouldNotify
prueba siempre se refiere a la mismaMyInheritedState
instancia, ¿no devolverá siemprefalse
? Ciertamente, elbuild
métodoMyInheritedState
es crear nuevas_MyInherited
instancias, pero eldata
campo siempre hace referencia athis
¿no? Tengo problemas ... Funciona si solo codificotrue
.TL; DR
No use mucho cálculo dentro del método updateShouldNotify y use const en lugar de new al crear un widget
En primer lugar, debemos entender qué son los objetos Widget, Element y Render.
Ahora estamos listos para sumergirnos en InheritedWidget y el método de BuildContext hereitFromWidgetOfExactType .
Como ejemplo, recomiendo que consideremos este ejemplo de la documentación de Flutter sobre InheritedWidget:
InheritedWidget: solo un widget que implementa en nuestro caso un método importante: updateShouldNotify . updateShouldNotify : una función que acepta un parámetro oldWidget y devuelve un valor booleano: verdadero o falso.
Como cualquier widget, InheritedWidget tiene un objeto Element correspondiente. Es InheritedElement . InheritedElement llama updateShouldNotify en el widget cada vez que construimos un nuevo widget (llama setState en un ancestro). Cuando updateShouldNotify devuelve true, InheritedElement itera a través de dependencias (?) Y llama al método didChangeDependencies en él.
¿Dónde InheritedElement obtiene las dependencias ? Aquí deberíamos mirar el método heritageFromWidgetOfExactType .
HereitFromWidgetOfExactType : este método definido en BuildContext y cada elemento implementa la interfaz BuildContext (Element == BuildContext). Entonces, cada elemento tiene este método.
Veamos el código de heritageFromWidgetOfExactType:
Aquí intentamos encontrar un antepasado en _inheritedWidgets mapeado por tipo. Si se encuentra el antepasado, llamamos hereitFromElement .
El código de hereitFromElement :
Entonces ahora sabemos de dónde obtiene InheritedElement sus dependencias.
Ahora veamos el método didChangeDependencies . Cada elemento tiene este método:
Como podemos ver, este método solo marca un elemento como sucio y este elemento debe reconstruirse en el siguiente cuadro. Reconstruir significa que el método de llamada se basa en el elemento del widget correspondiente.
Pero, ¿qué pasa con las "reconstrucciones completas del subárbol cuando reconstruyo InheritedWidget?". Aquí debemos recordar que los widgets son inmutables y si crea un nuevo widget, Flutter reconstruirá el subárbol. ¿Cómo podemos solucionarlo?
fuente
De los documentos :
Como señaló el OP, una
InheritedWidget
instancia no cambia ... pero se puede reemplazar con una nueva instancia en la misma ubicación en el árbol de widgets. Cuando eso suceda, es posible que los widgets registrados deban reconstruirse. ElInheritedWidget.updateShouldNotify
método hace esta determinación. (Ver: documentos )Entonces, ¿cómo podría reemplazarse una instancia? Una
InheritedWidget
instancia puede estar contenida por aStatefulWidget
, que puede reemplazar una instancia antigua por una nueva.fuente
InheritedWidget administra los datos centralizados de la aplicación y se los pasa al niño, como si pudiéramos almacenar aquí el recuento de carritos como se explica aquí :
fuente