flutter

flutter - ¿Cómo lidiar con la creación de widgets no deseados?



(1)

El método de construcción está diseñado de tal manera que debería ser puro / sin efectos secundarios . Esto se debe a que muchos factores externos pueden desencadenar una nueva creación de widget, como:

  • Ruta pop / push, para animaciones in / out
  • Cambiar el tamaño de la pantalla, generalmente debido a la apariencia del teclado o al cambio de orientación
  • El widget padre recreado su hijo
  • Un objeto InheritedWidget del widget depende del cambio ( Class.of(context) )

Esto significa que el método de build no debe activar una llamada http ni modificar ningún estado .

¿Cómo se relaciona esto con la pregunta?

El problema al que se enfrenta es que su método de compilación tiene efectos secundarios / no es puro, lo que hace que la llamada de compilación extraña sea problemática.

En lugar de evitar la llamada a la compilación, debe hacer que su método de compilación sea puro, de modo que pueda llamarlo en cualquier momento sin impacto.

En el caso de su ejemplo, transformaría su widget en un StatefulWidget luego extraería esa llamada HTTP al initState de initState de su State :

class Example extends StatefulWidget { @override _ExampleState createState() => _ExampleState(); } class _ExampleState extends State<Example> { Future<int> future; @override void initState() { future = Future.value(42); super.initState(); } @override Widget build(BuildContext context) { return FutureBuilder( future: future, builder: (context, snapshot) { // create some layout here }, ); } }

  • También es posible hacer un widget capaz de reconstruir sin obligar a sus hijos a construir también.

Cuando la instancia de un widget permanece igual; El revoloteo a propósito no reconstruirá a los niños. Implica que puede almacenar en caché partes de su árbol de widgets para evitar reconstrucciones innecesarias.

La forma más fácil es usar const dart const :

@override Widget build(BuildContext context) { return const DecoratedBox( decoration: BoxDecoration(), child: Text("Hello World"), ); }

Gracias a la palabra clave const , la instancia de DecoratedBox seguirá siendo la misma incluso si la compilación se llamara cientos de veces.

Pero puedes lograr el mismo resultado manualmente:

@override Widget build(BuildContext context) { final subtree = MyWidget( child: Text("Hello World") ); return StreamBuilder<String>( stream: stream, initialData: "Foo", builder: (context, snapshot) { return Column( children: <Widget>[ Text(snapshot.data), subtree, ], ); }, ); }

En este ejemplo, cuando se notifica a StreamBuilder los nuevos valores, el subtree no se reconstruirá incluso si StreamBuilder / Column lo hace. Sucede porque gracias al cierre, la instancia de MyWidget no cambió.

Este patrón se usa mucho en animaciones. Los usuarios típicos son AnimatedBuilder y todas las Transiciones * como AlignTransition .

También puede almacenar el subtree en un campo de su clase, aunque menos recomendado, ya que rompe la recarga en caliente.

Por varias razones, a veces se vuelve a llamar el método de build de mis widgets.

Sé que sucede porque un padre actualizado. Pero esto provoca efectos no deseados. Una situación típica en la que causa problemas es cuando se usa FutureBuilder esta manera:

@override Widget build(BuildContext context) { return FutureBuilder( future: httpCall(), builder: (context, snapshot) { // create some layout here }, ); }

En este ejemplo, si se volviera a llamar al método de compilación , se activaría otra solicitud http. Lo cual es indeseado.

Teniendo en cuenta esto, ¿cómo lidiar con la construcción no deseada? ¿Hay alguna manera de prevenir la llamada de construcción?