Ich habe festgestellt, dass es möglich ist, Widgets mit einfachen Funktionen zu erstellen, anstatt StatelessWidget zu unterordnen . Ein Beispiel wäre dies:
Widget function({ String title, VoidCallback callback }) {
return GestureDetector(
onTap: callback,
child: // some widget
);
}
Dies ist interessant, da es weit weniger Code erfordert als eine vollständige Klasse. Beispiel:
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
);
}
}
Ich habe mich also gefragt: Gibt es neben der Syntax einen Unterschied zwischen Funktionen und Klassen, um Widgets zu erstellen? Und ist es eine gute Praxis, Funktionen zu verwenden?
Antworten:
TL; DR: Verwenden Sie lieber Klassen als Funktionen, um einen wiederverwendbaren Widget-Baum zu erstellen.
EDIT : Um einige Missverständnisse auszugleichen: Hier geht es nicht um Funktionen, die Probleme verursachen, sondern um Klassen, die einige lösen.
Flutter hätte StatelessWidget nicht, wenn eine Funktion dasselbe tun könnte.
Ebenso richtet es sich hauptsächlich an öffentliche Widgets, die zur Wiederverwendung bestimmt sind. Es ist weniger wichtig, dass private Funktionen nur einmal verwendet werden - obwohl es immer noch gut ist, sich dieses Verhaltens bewusst zu sein.
Es gibt einen wichtigen Unterschied zwischen der Verwendung von Funktionen anstelle von Klassen, dh: Das Framework kennt keine Funktionen, kann jedoch Klassen sehen.
Betrachten Sie die folgende "Widget" -Funktion:
auf diese Weise verwendet:
Und es ist Klassenäquivalent:
so verwendet:
Auf dem Papier scheinen beide genau dasselbe zu tun: Erstellen Sie 2
Container
, wobei eines in das andere verschachtelt ist. Aber die Realität sieht etwas anders aus.Bei Funktionen sieht der generierte Widget-Baum folgendermaßen aus:
Während des Unterrichts lautet der Widget-Baum:
Dies ist wichtig, da sich dadurch das Verhalten des Frameworks beim Aktualisieren eines Widgets ändert.
Warum das wichtig ist
Durch die Verwendung von Funktionen zum Aufteilen Ihres Widget-Baums in mehrere Widgets setzen Sie sich Fehlern aus und verpassen einige Leistungsoptimierungen.
Es gibt keine Garantie , dass Sie werden Fehler haben von Funktionen, sondern von Klassen verwenden, werden Sie garantiert nicht , diese Fragen stellen.
Hier sind einige interaktive Beispiele auf Dartpad, die Sie selbst ausführen können, um die Probleme besser zu verstehen:
https://dartpad.dev/1870e726d7e04699bc8f9d78ba71da35
Dieses Beispiel zeigt, wie Sie durch Aufteilen Ihrer App in Funktionen versehentlich Dinge wie z
AnimatedSwitcher
https://dartpad.dev/a869b21a2ebd2466b876a5997c9cf3f1
Dieses Beispiel zeigt, wie Klassen detailliertere Neuerstellungen des Widget-Baums ermöglichen und die Leistung verbessern
https://dartpad.dev/06842ae9e4b82fad917acb88da108eee
Dieses Beispiel zeigt, wie Sie durch die Verwendung von Funktionen BuildContext missbrauchen und bei der Verwendung von InheritedWidgets (z. B. Theme oder Providern) auf Fehler stoßen.
Fazit
Hier ist eine kuratierte Liste der Unterschiede zwischen der Verwendung von Funktionen und Klassen:
showDialogs
& ähnliches unterbrechen )ClassWidget
in dem Widget-Baum, der vom devtool angezeigt wird, was hilft, zu verstehen, was auf dem Bildschirm angezeigt wirdWenn eine Ausnahme auftritt (wie ProviderNotFound), gibt Ihnen das Framework den Namen des aktuell erstellten Widgets. Wenn Sie Ihren Widget-Baum nur in Funktionen + aufgeteilt haben
Builder
, haben Ihre Fehler keinen hilfreichen NamenInsgesamt wird es aus diesen Gründen als schlechte Praxis angesehen, Funktionen über Klassen für die Wiederverwendung von Widgets zu verwenden.
Sie können , aber es kann Sie in der Zukunft beißen.
quelle
Ich habe in den letzten 2 Tagen zu diesem Thema recherchiert. Ich bin zu folgendem Schluss gekommen: Es ist OK, Teile der App in Funktionen zu zerlegen. Es ist nur ideal, dass diese Funktionen a zurückgeben
StatelessWidget
, damit Optimierungen vorgenommen werden können, z. B. das Erstellen desStatelessWidget
const
, damit es nicht neu erstellt wird, wenn es nicht muss. Zum Beispiel ist dieser Code vollkommen gültig:Die Verwendung der Funktion dort ist vollkommen in Ordnung, da sie a zurückgibt
const StatelessWidget
. Bitte korrigieren Sie mich, wenn ich falsch liege.quelle
const
für jeden Fall vor der zustandslosen Klasse verwenden? Oder müssen es bestimmte Fälle sein? Wenn ja, was sind sie?const
überall verwenden können. Wenn Sie beispielsweise eineStatelessWidget
Klasse haben, die einenText
Wert zurückgibt , der den Wert einer Variablen enthält, und diese Variable sich irgendwo ändert,StatelessWidget
sollte Ihre neu erstellt werden, damit sie diesen anderen Wert anzeigen kann, daher kann dies nicht der Fall seinconst
. Ich denke, der sichere Weg, es auszudrücken, ist folgender: Wo immer Sie können, verwenden Sie esconst
, wenn es sicher ist.Es gab einen großen Unterschied zwischen den Funktionen und der Klasse.
Lassen Sie es uns von Grund auf erklären. « (Nur über Imperativ)
Wir alle wissen, dass die Programmierhistorie mit einfachen Grundbefehlen begann (zB: Assembly).
Die nächste strukturierte Programmierung wurde mit Flusssteuerungen geliefert (z. B. if, switch, while, for usw.). Dieses Paradigma gibt Programmierern die Möglichkeit, den Programmfluss effektiv zu steuern und die Anzahl der Codezeilen durch Schleifen zu minimieren.
Als nächstes kam die prozedurale Programmierung, die Anweisungen in Prozeduren (Funktionen) gruppiert. Dies gab zwei Hauptvorteile für Programmierer.
1.Gruppenanweisungen (Operationen) in separate Blöcke.
2.Kann diese Blöcke wiederverwenden. (Funktionen)
Vor allem aber Paradigmen nicht geben , eine Lösung für Anwendungen verwalten. Die prozedurale Programmierung kann auch nur für kleine Anwendungen verwendet werden. Dies kann nicht für die Entwicklung großer Webanwendungen (z. B. Banking, Google, Youtube, Facebook, Stackoverflow usw.) verwendet werden. Es können keine Frameworks wie Android SDK, Flutter SDK und vieles mehr erstellt werden.
Daher recherchieren die Ingenieure viel mehr, um Programme ordnungsgemäß zu verwalten.
Schließlich bietet die objektorientierte Programmierung die gesamte Lösung für die Verwaltung von Anwendungen in jeder Größenordnung (von der Hallo-Welt bis zu Billionen von Menschen, die die Systemerstellung verwenden, z. B. Google, Amazon und heute 90% der Anwendungen).
In oop werden alle Anwendungen um Objekte herum erstellt. Dies bedeutet, dass die Anwendung eine Sammlung dieser Objekte ist.
Objekte sind also das Grundgebäude für jede Anwendung.
Gruppendaten und Funktionen der Klasse (Objekt zur Laufzeit) in Bezug auf diese Variablen (Daten). Objekt besteht also aus Daten und den damit verbundenen Operationen.
[Hier werde ich nicht über oop erklären]
»Okay, jetzt kommen wir zum Flattern.«
-Dart unterstützt sowohl prozedurale als auch oop-Funktionen. Das Flutter-Framework wird jedoch vollständig mithilfe von Klassen (oop) erstellt. (Weil ein großes verwaltbares Framework nicht mithilfe von Prozeduren erstellt werden kann.)
Hier werde ich eine Liste der Gründe erstellen, warum sie Klassen anstelle von Funktionen zum Erstellen von Widgets verwenden
1 - In den meisten Fällen ruft die Build-Methode (untergeordnetes Widget) die Anzahl der synchronen und asynchronen Funktionen auf.
Ex:
Daher muss die Build-Methode in einem separaten Klassen-Widget gespeichert werden (da alle anderen Methoden, die von der build () -Methode aufgerufen werden, in einer Klasse gespeichert werden können).
2 - Mit der Widget-Klasse können Sie die Nummer einer anderen Klasse erstellen, ohne immer wieder denselben Code zu schreiben (** Verwendung der Vererbung ** (erweitert)).
Mit Vererbung (Erweitern) und Polymorphismus (Überschreiben) können Sie auch eine eigene benutzerdefinierte Klasse erstellen. (Unten im Beispiel: Dort werde ich die Animation anpassen (überschreiben), indem ich MaterialPageRoute erweitere (weil ich den Standardübergang anpassen möchte) .👇
3 - Funktionen können keine Bedingungen für ihre Parameter hinzufügen, aber mit dem Konstruktor des Klassen-Widgets können Sie dies tun.
Unten Codebeispiel👇 (diese Funktion wird häufig von Framework-Widgets verwendet)
4 - Funktionen können const nicht verwenden und das Klassen-Widget kann die const für ihre Konstruktoren verwenden. (die die Leistung des Hauptthreads beeinflussen)
5 - Sie können eine beliebige Anzahl unabhängiger Widgets mit derselben Klasse (Instanzen einer Klasse / von Objekten) erstellen. Die Funktion kann jedoch keine unabhängigen Widgets (Instanz) erstellen, sondern wiederverwenden.
[Jede Instanz hat ihre eigene Instanzvariable und diese ist völlig unabhängig von anderen Widgets (Objekt). Die lokale Variable der Funktion hängt jedoch von jedem Funktionsaufruf ab * (dh wenn Sie einen Wert einer lokalen Variablen ändern, wirkt sich dies auf alle anderen Teile von aus die Anwendung, die diese Funktion verwendet)]
Es gab viele Vorteile in der Klasse gegenüber Funktionen. (Oben sind nur einige Anwendungsfälle aufgeführt.)
🤯 Mein letzter Gedanke
Verwenden Sie Funktionen also nicht als Baustein Ihrer Anwendung, sondern nur für Operationen. Andernfalls verursacht es viele nicht handhabbare Probleme, wenn Ihre Anwendung skalierbar wird .
📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍 📍📍📍📍📍📍📍
Sie können die Qualität des Programms nicht anhand der Anzahl der von ihm verwendeten Aussagen (oder Zeilen) messen
📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍 📍📍📍📍📍📍📍
Danke fürs Lesen
quelle
shrinkHelper() { return const SizedBox.shrink(); }
Dies entspricht der Verwendung vonconst SizedBox.shrink()
Inline in Ihrem Widget-Baum. Mithilfe von Hilfsfunktionen können Sie die Anzahl der Verschachtelungen an einer Stelle begrenzen.Stellen Sie beim Aufrufen des Flutter-Widgets sicher, dass Sie das Schlüsselwort const verwenden. Beispielsweise
const MyListWidget();
quelle
const
Schlüsselworts beim Aufrufen des überarbeiteten zustandslosen Widgets sollte es nur einmal aufgerufen werden.