Zdałem sobie sprawę, że możliwe jest tworzenie widgetów przy użyciu prostych funkcji zamiast tworzenia podklas StatelessWidget . Przykładem może być:
Widget function({ String title, VoidCallback callback }) {
return GestureDetector(
onTap: callback,
child: // some widget
);
}
Jest to interesujące, ponieważ wymaga znacznie mniej kodu niż pełnowymiarowa klasa. Przykład:
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
);
}
}
Więc zastanawiałem się: czy jest jakaś różnica poza składnią między funkcjami i klasami do tworzenia widżetów? Czy korzystanie z funkcji jest dobrą praktyką?
Odpowiedzi:
TL; DR: Preferuj używanie klas zamiast funkcji, aby utworzyć drzewo widżetów wielokrotnego użytku .
EDYCJA : Żeby nadrobić pewne nieporozumienia: nie chodzi o funkcje powodujące problemy, ale zajęcia rozwiązujące niektóre.
Flutter nie miałby StatelessWidget, gdyby funkcja mogła zrobić to samo.
Podobnie jest skierowany głównie do widżetów publicznych, stworzonych do ponownego wykorzystania. Nie ma to większego znaczenia dla funkcji prywatnych, które mają być używane tylko raz - chociaż świadomość tego zachowania jest nadal dobra.
Istnieje ważna różnica między używaniem funkcji zamiast klas, to znaczy: Framework nie zna funkcji, ale widzi klasy.
Rozważ następującą funkcję „widżetu”:
używany w ten sposób:
I jest to odpowiednik klasy:
używane w ten sposób:
Na papierze oba wydają się robić dokładnie to samo: Utwórz 2
Container
, z jednym zagnieżdżonym w drugim. Ale rzeczywistość jest nieco inna.W przypadku funkcji wygenerowane drzewo widżetów wygląda następująco:
W przypadku klas drzewo widżetów to:
Jest to ważne, ponieważ zmienia sposób, w jaki struktura zachowuje się podczas aktualizowania widgetu.
Dlaczego to ma znaczenie
Używając funkcji do podzielenia drzewa widżetów na wiele widżetów, narażasz się na błędy i pomijasz niektóre optymalizacje wydajności.
Nie ma gwarancji, że będziesz mieć błędy przy użyciu funkcji, ale używając klas, masz gwarancję, że nie napotkasz tych problemów.
Oto kilka interaktywnych przykładów na Dartpad, które możesz uruchomić samodzielnie, aby lepiej zrozumieć problemy:
https://dartpad.dev/1870e726d7e04699bc8f9d78ba71da35
Ten przykład pokazuje, jak dzieląc aplikację na funkcje, możesz przypadkowo zepsuć takie rzeczy jak
AnimatedSwitcher
https://dartpad.dev/a869b21a2ebd2466b876a5997c9cf3f1
Ten przykład pokazuje, w jaki sposób klasy umożliwiają bardziej szczegółowe przebudowywanie drzewa widżetów, poprawiając wydajność
https://dartpad.dev/06842ae9e4b82fad917acb88da108eee
Ten przykład pokazuje, jak za pomocą funkcji narażasz się na niewłaściwe użycie BuildContext i napotykasz błędy podczas korzystania z InheritedWidgets (takich jak motyw lub dostawcy)
Wniosek
Oto lista różnic między używaniem funkcji i klas:
showDialogs
)ClassWidget
w drzewie widżetów pokazanym przez devtool, które pomaga zrozumieć, co jest na ekranieJeśli wystąpi wyjątek (np. ProviderNotFound), framework poda nazwę aktualnie budowanego widżetu. Jeśli podzieliłeś drzewo widżetów tylko na functions +
Builder
, błędy nie będą miały użytecznej nazwyOgólnie rzecz biorąc, używanie funkcji zamiast klas w celu ponownego użycia widżetów jest uważane za złą praktykę z tych powodów.
Państwo może , ale może cię ugryźć w przyszłości.
źródło
Badałem ten problem przez ostatnie 2 dni. Doszedłem do następującego wniosku: w porządku jest rozbić elementy aplikacji na funkcje. Idealnie
StatelessWidget
byłoby, gdyby te funkcje zwracały a , więc można wprowadzić optymalizacje, takie jak tworzenieStatelessWidget
const
, więc nie odbudowuje się, jeśli nie musi. Na przykład ten fragment kodu jest całkowicie poprawny:Użycie tam funkcji jest w porządku, ponieważ zwraca a
const StatelessWidget
. Proszę popraw mnie jeżeli się mylę.źródło
const
w każdym przypadku możemy użyć przed klasą bezpaństwową? A może to muszą być określone przypadki? Jeśli tak, jakie one są?const
wszędzie. Na przykład, jeśli maszStatelessWidget
klasę, która zwraca aText
zawierającą wartość zmiennej i ta zmienna gdzieś się zmienia, to twojaStatelessWidget
powinna zostać przebudowana, więc może pokazać tę inną wartość, dlatego nie może byćconst
. Myślę, że można to bezpiecznie ująć w następujący sposób: gdziekolwiek możesz, używajconst
, jeśli jest to bezpieczne.Istniała duża różnica między tym, co robi funkcje, a tym, co robi klasa.
Pozwólcie, że wyjaśnię to od podstaw. (Tylko o imperatyw)
Historia programowania, którą wszyscy znamy, rozpoczęła się od prostych poleceń podstawowych (np. -: Assembly).
Next Strukturalne programowanie przyszło z kontrolkami przepływu (np .-: if, switch, while, for etc) Ten paradygmat daje programistom efektywną kontrolę przepływu programu, a także minimalizuje liczbę linii kodu przez pętle.
Następnie przyszło programowanie proceduralne, które grupuje instrukcje w procedury (funkcje). Dało to dwie główne korzyści dla programistów.
1. Grupuj instrukcje (operacje) w oddzielnych blokach.
2. Potrafi ponownie wykorzystać te bloki. (Funkcje)
Ale przede wszystkim paradygmaty nie dawały rozwiązania do zarządzania aplikacjami. Programowanie proceduralne może być również używane tylko w aplikacjach na małą skalę. Nie można tego używać do tworzenia dużych aplikacji internetowych (np.: Bankowość, Google, youtube, facebook, stackoverflow itp.), Nie można tworzyć frameworków, takich jak android sdk, flutter sdk i wiele więcej ......
Dlatego inżynierowie przeprowadzają znacznie więcej badań, aby właściwie zarządzać programami.
Wreszcie programowanie obiektowe zawiera całe rozwiązanie do zarządzania aplikacjami w dowolnej skali (od hello world do bilionów ludzi korzystających z tworzenia systemów, np.-Google, amazon, a dziś 90% aplikacji).
W oop wszystkie aplikacje są zbudowane wokół obiektów, co oznacza, że aplikacja jest zbiorem tych obiektów.
więc obiekty są podstawowym budynkiem dla każdej aplikacji.
class (obiekt w czasie wykonywania) grupuje dane i funkcje związane z tymi zmiennymi (dane). więc obiekt składa się z danych i powiązanych z nimi operacji.
[Tutaj nie mam zamiaru wyjaśniać oop]
👉👉👉Ok Now Lets come for flutter framework.
-Dart obsługuje zarówno procedury, jak i oop Ale framework Flutter jest całkowicie zbudowany przy użyciu klas (oop). (Ponieważ duże, łatwe w zarządzaniu ramy nie mogą tworzyć przy użyciu procedur)
Tutaj utworzę listę powodów, dla których używają klas zamiast funkcji do tworzenia widżetów
1 - W większości przypadków metoda budowania (widget potomny) wywołuje numer funkcji synchronicznej i asynchronicznej.
Dawny:
więc metoda budowania musi być przechowywana w osobnym widżecie klasy (ponieważ wszystkie inne metody wywoływane przez metodę build () mogą przechowywać się w jednej klasie)
2 - Korzystając z klasy widżetu możesz utworzyć numer innej klasy bez ponownego pisania tego samego kodu (** Use Of Inheritance ** (extends)).
A także używając dziedziczenia (rozszerzanie) i polimorfizmu (nadpisywanie) możesz stworzyć własną klasę niestandardową. (Przykład poniżej, w tym miejscu dostosuję (Zastąp) animację, rozszerzając MaterialPageRoute (ponieważ domyślne przejście chcę dostosować).
3 - Funkcje nie mogą dodawać warunków do swoich parametrów, ale możesz to zrobić za pomocą konstruktora widżetu klasy.
Poniżej przykład kodu👇 (ta funkcja jest intensywnie używana przez widżety frameworka)
4 - Funkcje nie mogą używać stałej, a widżet klasy może używać stałej dla swoich konstruktorów. (które wpływają na wydajność głównego wątku)
5 - Możesz utworzyć dowolną liczbę niezależnych widżetów przy użyciu tej samej klasy (instancji klasy / obiektów), ale funkcja nie może tworzyć niezależnych widżetów (instancji), ale może to zrobić ponownie.
[każda instancja ma własną zmienną instancji, która jest całkowicie niezależna od innych widżetów (obiektów), ale zmienna lokalna funkcji jest zależna od każdego wywołania funkcji * (co oznacza, że zmiana wartości zmiennej lokalnej wpływa na wszystkie inne części aplikacja korzystająca z tej funkcji)]
Klasa miała wiele zalet w porównaniu z funkcjami ... (powyżej podano tylko kilka przypadków użycia)
🤯 Moja ostatnia myśl
Dlatego nie używaj funkcji jako elementu konstrukcyjnego aplikacji, używaj ich tylko do wykonywania operacji. W przeciwnym razie, gdy aplikacja stanie się skalowalna, spowoduje wiele nieporęcznych problemów .
📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍 📍📍📍📍📍📍📍
NIE MOŻESZ ZMIERZYĆ JAKOŚCI PROGRAMU WEDŁUG LICZBY WYRAŻEŃ (lub LINII).
📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍 📍📍📍📍📍📍📍
Dziękuje za przeczytanie
źródło
shrinkHelper() { return const SizedBox.shrink(); }
działa tak samo, jak użycieconst SizedBox.shrink()
inline w drzewie widżetów, a korzystając z funkcji pomocniczych, możesz ograniczyć liczbę zagnieżdżeń w jednym miejscu.Podczas wywoływania widżetu Flutter upewnij się, że używasz słowa kluczowego const. Na przykład
const MyListWidget();
źródło
const
słowo kluczowe podczas wywoływania refaktoryzowanego bezstanowego widgetu, powinno ono zostać wywołane tylko raz.