Me he dado cuenta de que es posible crear widgets usando funciones simples en lugar de subclasificar StatelessWidget . Un ejemplo sería este:
Widget function({ String title, VoidCallback callback }) {
return GestureDetector(
onTap: callback,
child: // some widget
);
}
Esto es interesante porque requiere mucho menos código que una clase completa. Ejemplo:
class SomeWidget extends StatelessWidget {
final VoidCallback callback;
final String title;
const SomeWidget({Key key, this.callback, this.title}) : super(key: key);
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: callback,
child: // some widget
);
}
}
Entonces me he estado preguntando: ¿Existe alguna diferencia además de la sintaxis entre las funciones y las clases para crear widgets? ¿Y es una buena práctica utilizar funciones?
Respuestas:
TL; DR: Prefiere usar clases sobre funciones para hacer un árbol de widgets reutilizable .
EDITAR : Para compensar algunos malentendidos: no se trata de funciones que causan problemas, sino de clases que resuelven algunos.
Flutter no tendría StatelessWidget si una función pudiera hacer lo mismo.
Asimismo, está dirigido principalmente a widgets públicos, hechos para ser reutilizados. No importa tanto que las funciones privadas diseñadas para usarse solo una vez, aunque ser consciente de este comportamiento sigue siendo bueno.
Hay una diferencia importante entre usar funciones en lugar de clases, es decir: el marco no conoce las funciones, pero puede ver las clases.
Considere la siguiente función de "widget":
usado de esta manera:
Y es equivalente de clase:
usado así:
Sobre el papel, ambos parecen hacer exactamente lo mismo: crear 2
Container
, con uno anidado en el otro. Pero la realidad es un poco diferente.En el caso de las funciones, el árbol de widgets generado se ve así:
Mientras que con las clases, el árbol de widgets es:
Esto es importante porque cambia la forma en que se comporta el marco al actualizar un widget.
Por que importa
Al usar funciones para dividir su árbol de widgets en múltiples widgets, se expone a errores y se pierde algunas optimizaciones de rendimiento.
No hay garantía de que va a tener errores mediante el uso de funciones, pero mediante el uso de clases, usted está garantizado para no hacer frente a estos problemas.
Aquí hay algunos ejemplos interactivos en Dartpad que puede ejecutar usted mismo para comprender mejor los problemas:
https://dartpad.dev/1870e726d7e04699bc8f9d78ba71da35
Este ejemplo muestra cómo al dividir su aplicación en funciones, puede romper accidentalmente cosas como
AnimatedSwitcher
https://dartpad.dev/a869b21a2ebd2466b876a5997c9cf3f1
Este ejemplo muestra cómo las clases permiten reconstrucciones más granulares del árbol de widgets, mejorando el rendimiento
https://dartpad.dev/06842ae9e4b82fad917acb88da108eee
Este ejemplo muestra cómo, al usar funciones, se expone a hacer un mal uso de BuildContext y enfrentar errores cuando usa InheritedWidgets (como Theme o proveedores)
Conclusión
Aquí hay una lista seleccionada de las diferencias entre el uso de funciones y clases:
showDialogs
y similares)ClassWidget
en el árbol de widgets que muestra la herramienta devtool, que ayuda a comprender lo que hay en la pantallaSi ocurre una excepción (como ProviderNotFound), el marco le dará el nombre del widget de construcción actual. Si ha dividido su árbol de widgets solo en funciones +
Builder
, sus errores no tendrán un nombre útilEn general, se considera una mala práctica usar funciones sobre clases para reutilizar widgets debido a estas razones.
Usted puede , pero te puede morder en el futuro.
fuente
He estado investigando este problema durante los últimos 2 días. Llegué a la siguiente conclusión: está BIEN dividir partes de la aplicación en funciones. Es ideal que esas funciones devuelvan a
StatelessWidget
, para que se puedan realizar optimizaciones, como hacerStatelessWidget
const
, para que no se reconstruya si no es necesario. Por ejemplo, este fragmento de código es perfectamente válido:El uso de la función allí está perfectamente bien, ya que devuelve un
const StatelessWidget
. Por favor corrígeme si estoy equivocado.fuente
const
delante de la clase sin estado para cada caso? ¿O tienen que ser ciertos casos? Si es así, ¿cuáles son?const
todas partes. Por ejemplo, si tiene unaStatelessWidget
clase que devuelve un queText
contiene el valor de una variable, y esa variable cambia en algún lugar, entoncesStatelessWidget
debe reconstruirse, por lo que puede mostrar ese valor diferente, por lo tanto, no puede serconst
. Creo que la forma segura de decirlo es esta: siempre que pueda, úseloconst
, si es seguro hacerlo.Había una gran diferencia entre lo que hace la función y lo que hace la clase.
Deja que te lo explique desde cero . 🙂 (solo sobre imperativo)
El historial de programación, todos sabemos que comenzó con comandos básicos directos (por ejemplo: Ensamblaje).
Siguiente La programación estructurada vino con controles de flujo (por ejemplo, si, cambiar, mientras, para, etc.) Este paradigma permite a los programadores controlar el flujo del programa de manera eficaz y también minimizar el número de líneas de código por bucles.
Luego vino la programación procedimental y que agrupa las instrucciones en procedimientos (funciones). Esto dio dos importantes beneficios para los programadores.
1. Agrupe las declaraciones (operaciones) en bloques separados.
2.Puede reutilizar estos bloques. (Funciones)
Pero sobre todo los paradigmas no dieron una solución para la gestión de aplicaciones. La programación por procedimientos también solo se puede utilizar para aplicaciones a pequeña escala. Eso no se puede usar para desarrollar aplicaciones web grandes (por ejemplo: banca, google, youtube, facebook, stackoverflow, etc.), no se pueden crear marcos como android sdk, flutter sdk y mucho más ...
De modo que los ingenieros investigan mucho más para gestionar los programas de forma adecuada.
Finalmente, la Programación Orientada a Objetos viene con todas las soluciones para administrar aplicaciones a cualquier escala (desde hello world hasta billones de personas que utilizan la creación de sistemas, por ejemplo, google, amazon y hoy el 90% de las aplicaciones).
En oop, todas las aplicaciones se basan en objetos, lo que significa que la aplicación es una colección de estos objetos.
por lo que los objetos son el edificio básico para cualquier aplicación.
clase (objeto en tiempo de ejecución) grupo de datos y funciones relacionadas con esas variables (datos). para que el objeto se componga de datos y sus operaciones relacionadas.
[Aquí no voy a explicar sobre oop]
👉👉👉Ok Now Vayamos para flutter framework.👈👈👈
-Dart soporta tanto procedural como oop Pero, el framework Flutter se construye completamente usando clases (oop). (Porque un gran marco manejable no se puede crear usando procedimientos)
Aquí crearé una lista de razones por las que usan clases en lugar de funciones para hacer widgets.
1 - La mayoría de las veces, el método de construcción (widget secundario) llama al número de funciones sincrónicas y asincrónicas.
Ex:
por lo que el método de compilación debe mantenerse en un widget de clase separado (porque todos los demás métodos llamados por el método build () pueden mantenerse en una clase)
2 - Usando la clase de widget, puede crear un número de otra clase sin escribir el mismo código una y otra vez (** Uso de herencia ** (extiende)).
Y también usando herencia (extender) y polimorfismo (anular) puede crear su propia clase personalizada. (Abajo del ejemplo, allí personalizaré (Anularé) la animación extendiendo MaterialPageRoute (porque quiero personalizar su transición predeterminada) .👇
3 - Las funciones no pueden agregar condiciones para sus parámetros, pero usando el constructor del widget de clase puede hacerlo.
Ejemplo de código a continuación👇 (esta función es muy utilizada por los widgets de marco)
4 - Las funciones no pueden usar const y el widget Class puede usar const para sus constructores. (que afectan el rendimiento del hilo principal)
5 - Puede crear cualquier número de widgets independientes usando la misma clase (instancias de una clase / objetos) Pero la función no puede crear widgets independientes (instancia), pero la reutilización sí.
[cada instancia tiene su propia variable de instancia y eso es completamente independiente de otros widgets (objeto), pero la variable local de la función depende de cada llamada de función * (lo que significa que cuando cambia un valor de una variable local afecta a todas las demás partes de la aplicación que utiliza esta función)]
Hubo muchas ventajas en la clase sobre las funciones ... (arriba son solo algunos casos de uso)
🤯 Mi pensamiento final
Por lo tanto, no use las funciones como bloques de construcción de su aplicación, úselas solo para realizar operaciones. De lo contrario, causa muchos problemas imposibles de manejar cuando su aplicación se vuelve escalable .
📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍 📍📍📍📍📍📍📍
NO SE PUEDE MEDIR LA CALIDAD DEL PROGRAMA POR EL NÚMERO DE DECLARACIONES (o líneas) que utiliza
📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍 📍📍📍📍📍📍📍
Gracias por leer
fuente
shrinkHelper() { return const SizedBox.shrink(); }
es lo mismo que usarconst SizedBox.shrink()
en línea en su árbol de widgets, y al usar funciones auxiliares puede limitar la cantidad de anidamiento en un lugar.Cuando llame al widget Flutter, asegúrese de usar la palabra clave const. Por ejemplo
const MyListWidget();
fuente
const
palabra clave al llamar al widget sin estado refactorizado, solo se debe llamar una vez.