Chciałbym móc uruchamiać funkcje po zakończeniu budowania / ładowania widżetu, ale nie jestem pewien, jak to zrobić. Moim obecnym przypadkiem jest sprawdzenie, czy użytkownik jest uwierzytelniony, a jeśli nie, przekierowanie do widoku logowania. Nie chcę sprawdzać wcześniej i naciskać ani widoku logowania, ani widoku głównego, musi to nastąpić po załadowaniu widoku głównego. Czy jest coś, czego mogę użyć, aby to zrobić?
137
build
. Build można wywołać w dowolnym momencie wielokrotnie.Odpowiedzi:
Możesz użyć
https://github.com/slightfoot/flutter_after_layout
który wykonuje funkcję tylko raz po ukończeniu układu. Lub po prostu spójrz na jego implementację i dodaj do swojego kodu :-)
Co jest w zasadzie
void initState() { super.initState(); WidgetsBinding.instance .addPostFrameCallback((_) => yourFunction(context)); }
źródło
WidgetsBinding.instance.addPostFrameCallback((_) => yourFunciton(context));
już nie działainitState
np. wbuild
.setState
w ciąguyourFunction
metody, aby to działaAKTUALIZACJA: Flutter v1.8.4
Oba wymienione kody teraz działają:
import 'package:flutter/scheduler.dart'; SchedulerBinding.instance.addPostFrameCallback((_) => yourFunction(context));
źródło
NoSuchMethodError (NoSuchMethodError: The method 'addPostFrameCallback' was called on null. Receiver: null
Istnieją 3 możliwe sposoby:
1) WidgetsBinding.instance.addPostFrameCallback((_) => yourFunc(context)); 2) Future.delayed(Duration.zero, () => yourFunc(context)); 3) Timer.run(() => yourFunc(context));
A jeśli chodzi o
context
, potrzebowałem go do użyciaScaffold.of(context)
po wyrenderowaniu wszystkich moich widżetów.Ale moim skromnym zdaniem najlepszym sposobem na to jest:
void main() async { WidgetsFlutterBinding.ensureInitialized(); //all widgets are rendered here await yourFunc(); runApp( MyApp() ); }
źródło
Flutter 1.2 - strzałka 2.2
Zgodnie z oficjalnymi wytycznymi i źródłami, jeśli chcesz mieć pewność, że narysowana została również ostatnia klatka Twojego layoutu , możesz napisać np .:
import 'package:flutter/scheduler.dart'; void initState() { super.initState(); if (SchedulerBinding.instance.schedulerPhase == SchedulerPhase.persistentCallbacks) { SchedulerBinding.instance.addPostFrameCallback((_) => yourFunction(context)); } }
źródło
Jeśli szukasz
componentDidMount
odpowiednika ReactNative , Flutter go ma. To nie jest takie proste, ale działa w ten sam sposób. We FlutterzeWidget
s nie obsługują bezpośrednio swoich zdarzeń. Zamiast tego używająState
do tego celu.class MyWidget extends StatefulWidget{ @override State<StatefulWidget> createState() => MyState(this); Widget build(BuildContext context){...} //build layout here void onLoad(BuildContext context){...} //callback when layout build done } class MyState extends State<MyWidget>{ MyWidget widget; MyState(this.widget); @override Widget build(BuildContext context) => widget.build(context); @override void initState() => widget.onLoad(context); }
State.initState
zostanie wywołana natychmiast po zakończeniu renderowania układu przez screen. I nigdy więcej nie zostanie wywołany, nawet przy ponownym ładowaniu na gorąco, jeśli jesteś w trybie debugowania, dopóki wyraźnie nie osiągnie czasu, aby to zrobić.źródło
StatefulWidget
klasy do obsługiState
obiektu tak jak a,StatelessWidget
ale zdecydowanie tego nie polecam. Nie znalazłem jeszcze żadnego problemu, aleState
najpierw spróbuj zaimplementować wszystko wewnątrz obiektucomponentWillMount
tuż przed renderowaniem layoutu. Flutter zapewnia prostsze rozwiązanie.initState
wystarczy zarówno do pobierania danych, jak i renderowania układu, jeśli wiemy, jak to zrobić poprawnieW wersji Flutter 1.14.6, Dart w wersji 28.
Poniżej znajduje się, co zadziałało w moim przypadku. Po prostu musisz spakować wszystko, co chcesz, aby wydarzyło się po metodzie kompilacji, w osobną metodę lub funkcję.
@override void initState() { super.initState(); print('hello girl'); WidgetsBinding.instance .addPostFrameCallback((_) => afterLayoutWidgetBuild()); }
źródło
Najlepsze sposoby na zrobienie tego,
1. WidgetsBinding
WidgetsBinding.instance.addPostFrameCallback((_) { print("WidgetsBinding"); });
2. WidgetsBinding
SchedulerBinding.instance.addPostFrameCallback((_) { print("SchedulerBinding"); });
Można go wywołać wewnątrz
initState
, oba zostaną wywołane tylko raz po zakończeniu renderowania widgetów Build.@override void initState() { // TODO: implement initState super.initState(); print("initState"); WidgetsBinding.instance.addPostFrameCallback((_) { print("WidgetsBinding"); }); SchedulerBinding.instance.addPostFrameCallback((_) { print("SchedulerBinding"); }); }
oba powyższe kody będą działać tak samo, ponieważ oba używają podobnej struktury powiązań. Aby zobaczyć różnicę, znajdź poniższy link.
https://medium.com/flutterworld/flutter-schedulerbinding-vs-widgetsbinding-149c71cb607f
źródło
Wypróbuj SchedulerBinding,
SchedulerBinding.instance .addPostFrameCallback((_) => setState(() { isDataFetched = true; }));
źródło
Jeśli chcesz to zrobić tylko raz, zrób to, ponieważ Framework wywoła
initState()
metodę dokładnie raz dla każdego utworzonego obiektu State.@override void initState() { super.initState(); WidgetsBinding.instance .addPostFrameCallback((_) => executeAfterBuildComplete(context)); }
Jeśli chcesz to robić raz po raz, jak z tyłu lub przejść do następnego ekranu itp., Zrób to, ponieważ
didChangeDependencies()
Called, gdy zmienia się zależność tego obiektu State.Na przykład, jeśli poprzednie wywołanie
build
odwoływało się do elementu,InheritedWidget
który później się zmienił, struktura wywoła tę metodę, aby powiadomić ten obiekt o zmianie.Ta metoda jest również wywoływana bezpośrednio po
initState
. DzwonienieBuildContext.dependOnInheritedWidgetOfExactType
z tej metody jest bezpieczne .@override void didChangeDependencies() { super.didChangeDependencies(); WidgetsBinding.instance .addPostFrameCallback((_) => executeAfterBuildComplete(context)); }
To jest twoja funkcja oddzwaniania
executeAfterBuildComplete([BuildContext context]){ print("Build Process Complete"); }
źródło