J'ai réalisé qu'il est possible de créer des widgets en utilisant des fonctions simples au lieu de sous- classer StatelessWidget . Un exemple serait celui-ci:
Widget function({ String title, VoidCallback callback }) {
return GestureDetector(
onTap: callback,
child: // some widget
);
}
Ceci est intéressant car il nécessite beaucoup moins de code qu'une classe à part entière. Exemple:
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
);
}
}
Je me suis donc demandé: y a-t-il une différence en plus de la syntaxe entre les fonctions et les classes pour créer des widgets? Et est-ce une bonne pratique d'utiliser des fonctions?
Réponses:
TL; DR: Préférez utiliser des classes plutôt que des fonctions pour créer une arborescence de widgets réutilisable .
EDIT : Pour compenser certains malentendus: il ne s'agit pas de fonctions causant des problèmes, mais de classes en résolvant certains.
Flutter n'aurait pas StatelessWidget si une fonction pouvait faire la même chose.
De même, il s'adresse principalement aux widgets publics, faits pour être réutilisés. Cela n'a pas autant d'importance pour les fonctions privées conçues pour être utilisées qu'une seule fois - bien qu'il soit toujours bon d'être conscient de ce comportement.
Il existe une différence importante entre l'utilisation de fonctions au lieu de classes, c'est-à-dire: le framework ne connaît pas les fonctions, mais peut voir les classes.
Considérez la fonction "widget" suivante:
utilisé de cette façon:
Et c'est l'équivalent de la classe:
utilisé comme ça:
Sur le papier, les deux semblent faire exactement la même chose: Create 2
Container
, avec l'un imbriqué dans l'autre. Mais la réalité est légèrement différente.Dans le cas des fonctions, l'arborescence de widgets générée ressemble à ceci:
Alors qu'avec les classes, l'arborescence des widgets est:
Ceci est important car cela change le comportement du framework lors de la mise à jour d'un widget.
Pourquoi c'est important
En utilisant des fonctions pour diviser votre arborescence de widgets en plusieurs widgets, vous vous exposez à des bogues et manquez certaines optimisations de performances.
Il n'y a aucune garantie que vous aurez des bogues en utilisant des fonctions, mais en utilisant des classes, vous êtes assuré de ne pas faire face à ces problèmes.
Voici quelques exemples interactifs sur Dartpad que vous pouvez exécuter vous-même pour mieux comprendre les problèmes:
https://dartpad.dev/1870e726d7e04699bc8f9d78ba71da35
Cet exemple montre comment, en divisant votre application en fonctions, vous pouvez accidentellement casser des choses comme
AnimatedSwitcher
https://dartpad.dev/a869b21a2ebd2466b876a5997c9cf3f1
Cet exemple montre comment les classes permettent des reconstructions plus granulaires de l'arborescence des widgets, améliorant ainsi les performances
https://dartpad.dev/06842ae9e4b82fad917acb88da108eee
Cet exemple montre comment, en utilisant des fonctions, vous vous exposez à une mauvaise utilisation de BuildContext et à faire face à des bogues lors de l'utilisation d'InheritedWidgets (tels que Thème ou fournisseurs)
Conclusion
Voici une liste organisée des différences entre l'utilisation de fonctions et de classes:
showDialogs
et similaire)ClassWidget
dans l'arborescence des widgets montrée par le devtool, qui aide à comprendre ce qui est à l'écranSi une exception se produit (comme ProviderNotFound), le framework vous donnera le nom du widget en cours de construction. Si vous avez divisé votre arborescence de widgets uniquement en fonctions +
Builder
, vos erreurs n'auront pas de nom utileDans l'ensemble, il est considéré comme une mauvaise pratique d'utiliser des fonctions sur des classes pour réutiliser des widgets pour ces raisons.
Vous pouvez , mais cela peut vous mordre à l'avenir.
la source
Je fais des recherches sur ce problème depuis 2 jours. Je suis arrivé à la conclusion suivante: il est OK de décomposer des éléments de l'application en fonctions. Il est juste idéal que ces fonctions renvoient a
StatelessWidget
, donc des optimisations peuvent être faites, comme faire leStatelessWidget
const
, afin qu'il ne se reconstruise pas si ce n'est pas nécessaire. Par exemple, ce morceau de code est parfaitement valide:L'utilisation de la fonction y est parfaitement correcte, car elle renvoie un fichier
const StatelessWidget
. Corrigez-moi si j'ai tort, s'il-vous plait.la source
const
devant la classe sans état pour chaque cas? Ou faut-il que ce soit certains cas? Si oui, quels sont-ils?const
partout. Par exemple, si vous avez uneStatelessWidget
classe qui renvoie uneText
contenant la valeur d'une variable, et que cette variable change quelque part, alors vousStatelessWidget
devriez être reconstruite pour qu'elle puisse afficher cette valeur différente, donc elle ne peut pas l'êtreconst
. Je pense que le moyen le plus sûr de le mettre est le suivant: partout où vous le pouvez, utilisez-leconst
, si cela est sécuritaire.Il y avait une grande différence entre ce que font les fonctions et ce que fait la classe.
Permettez-moi de l'expliquer à partir de zéro. (Uniquement à propos de l'impératif)
L'historique de la programmation, nous le savons tous, a commencé avec des commandes simples de base (par exemple: Assemblage).
La programmation structurée suivante est venue avec des contrôles de flux (par exemple: if, switch, while, for etc). Ce paradigme permet aux programmeurs de contrôler efficacement le flux du programme et aussi de minimiser le nombre de lignes de code par des boucles.
Ensuite, la programmation procédurale est venue et qui regroupe les instructions en procédures (fonctions). Cela a donné deux avantages majeurs aux programmeurs.
1. Groupez les instructions (opérations) en blocs séparés.
2.Peut réutiliser ces blocs. (Fonctions)
Mais surtout, les paradigmes ne donnaient pas de solution pour la gestion des applications. La programmation procédurale ne peut également être utilisée que pour des applications à petite échelle. Cela ne peut pas être utilisé pour développer de grandes applications Web (par exemple: banque, google, youtube, facebook, stackoverflow, etc.), ne peut pas créer de frameworks comme android sdk, flutter sdk et bien plus encore ......
Les ingénieurs font donc beaucoup plus de recherches pour gérer correctement les programmes.
Enfin, la programmation orientée objet est livrée avec toute la solution pour gérer des applications à toutes les échelles (de hello world à des milliards de personnes utilisant la création de système, par exemple, google, amazon et aujourd'hui 90% des applications).
Dans oop, toutes les applications sont construites autour d'objets, cela signifie que l'application est une collection de ces objets.
les objets sont donc le bâtiment de base pour toute application.
class (objet lors de l'exécution) regroupe les données et les fonctions liées à ces variables (données). donc objet compose de données et de leurs opérations connexes.
[Ici, je ne vais pas expliquer à propos de oop]
👉👉👉Ok Now Permet de venir pour le cadre de flutter.👈👈👈
-Dart prend en charge à la fois procédural et oop Mais, le framework Flutter est entièrement construit en utilisant des classes (oop). (Parce qu'un grand cadre gérable ne peut pas créer à l'aide de procédures)
Ici, je vais créer une liste des raisons pour lesquelles ils utilisent des classes à la place des fonctions pour créer des widgets.
1 - La plupart du temps, la méthode de construction (widget enfant) appelle le numéro des fonctions synchrones et asynchrones.
Ex:
donc la méthode de construction doit rester dans un widget de classe séparé (car toutes les autres méthodes appelées par la méthode build () peuvent rester dans une classe)
2 - En utilisant la classe de widget, vous pouvez créer le numéro d'une autre classe sans écrire le même code encore et encore (** Use Of Inheritance ** (extend)).
Et aussi en utilisant l'héritage (étendre) et le polymorphisme (remplacement), vous pouvez créer votre propre classe personnalisée. (Dans l'exemple ci-dessous, je vais personnaliser (remplacer) l'animation en étendant MaterialPageRoute (parce que sa transition par défaut que je veux personnaliser).
3 - Les fonctions ne peuvent pas ajouter de conditions pour leurs paramètres, mais en utilisant le constructeur du widget de classe Vous pouvez le faire.
Ci-dessous l'exemple de code👇 (cette fonctionnalité est fortement utilisée par les widgets du framework)
4 - Les fonctions ne peuvent pas utiliser const et le widget Class peut utiliser le const pour leurs constructeurs. (qui affectent les performances du thread principal)
5 - Vous pouvez créer n'importe quel nombre de widgets indépendants en utilisant la même classe (instances d'une classe / objets) Mais la fonction ne peut pas créer de widgets indépendants (instance), mais la réutilisation le peut.
[chaque instance a sa propre variable d'instance et totalement indépendante des autres widgets (objet), mais la variable locale de la fonction dépend de chaque appel de fonction * (ce qui signifie que lorsque vous modifiez une valeur d'une variable locale, cela affecte toutes les autres parties de l'application qui utilise cette fonction)]
Il y avait de nombreux avantages en classe par rapport aux fonctions. (Ci-dessus ne sont que quelques cas d'utilisation)
🤯 Ma dernière pensée
N'utilisez donc pas les fonctions comme élément constitutif de votre application, utilisez-les uniquement pour effectuer des opérations. Sinon, cela pose de nombreux problèmes difficiles à gérer lorsque votre application devient évolutive .
📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍 📍📍📍📍📍📍📍
VOUS NE POUVEZ PAS MESURER LA QUALITÉ DU PROGRAMME PAR NOMBRE DE DÉCLARATIONS (ou de lignes) UTILISÉES PAR lui
📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍 📍📍📍📍📍📍📍
Merci d'avoir lu
la source
shrinkHelper() { return const SizedBox.shrink(); }
est identique à l'utilisation enconst SizedBox.shrink()
ligne dans votre arborescence de widgets, et en utilisant les fonctions d'assistance, vous pouvez limiter la quantité d'imbrication en un seul endroit.Lorsque vous appelez le widget Flutter, assurez-vous d'utiliser le mot-clé const. Par exemple
const MyListWidget();
la source
const
mot - clé lors de l'appel du widget sans état refactoré, il ne doit être appelé qu'une seule fois.