Dart 颤振:小部件构建完成时运行方法
我希望能够在小部件完成构建/加载后运行功能,但我不确定如何运行。 我当前的用例是检查用户是否经过身份验证,如果没有,则重定向到登录视图。我不想在登录视图或主视图加载之前进行检查和推送,它需要在主视图加载之后进行。 有什么我可以用的吗?你可以用 它在布局完成后只执行一次函数。 或者只需查看其实现并将其添加到代码中:-) 基本上Dart 颤振:小部件构建完成时运行方法,dart,flutter,Dart,Flutter,我希望能够在小部件完成构建/加载后运行功能,但我不确定如何运行。 我当前的用例是检查用户是否经过身份验证,如果没有,则重定向到登录视图。我不想在登录视图或主视图加载之前进行检查和推送,它需要在主视图加载之后进行。 有什么我可以用的吗?你可以用 它在布局完成后只执行一次函数。 或者只需查看其实现并将其添加到代码中:-) 基本上 void initState() { super.initState(); WidgetsBinding.instance .addP
void initState() {
super.initState();
WidgetsBinding.instance
.addPostFrameCallback((_) => yourFunction(context));
}
如果您正在寻找ReactNative的
componentDidMount
等效产品,则Flatter拥有它。虽然没那么简单,但它的工作原理是一样的。在flatter中,Widget
s不直接处理它们的事件。相反,它们使用它们的状态
对象来实现这一点
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);
}
类MyWidget扩展了StatefulWidget{
@凌驾
State createState()=>MyState(这个);
小部件生成(BuildContext上下文){…}//此处生成布局
void onLoad(BuildContext上下文){…}//布局生成完成时回调
}
类MyState扩展状态{
我的小部件;
MyState(this.widget);
@凌驾
Widget build(BuildContext)=>Widget.build(context);
@凌驾
void initState()=>widget.onLoad(上下文);
}
State。一旦屏幕完成布局渲染,将立即调用initState
。如果您处于调试模式,则即使在热重新加载时也不会再次调用,直到显式到达调用时间。更新:颤振v1.8.4
上述两种代码现在都在运行:
工作:
工作
颤振1.2-省道2.2
根据官方指南,如果您想确定布局的最后一帧也已绘制,您可以写下例如:
import 'package:flutter/scheduler.dart';
void initState() {
super.initState();
if (SchedulerBinding.instance.schedulerPhase == SchedulerPhase.persistentCallbacks) {
SchedulerBinding.instance.addPostFrameCallback((_) => yourFunction(context));
}
}
试试SchedulerBinding
SchedulerBinding.instance
.addPostFrameCallback((_) => setState(() {
isDataFetched = true;
}));
在颤振版本1.14.6和Dart版本28中。 下面是对我有效的方法,您只需要将构建方法之后希望发生的所有事情捆绑到一个单独的方法或函数中
@override
void initState() {
super.initState();
print('hello girl');
WidgetsBinding.instance
.addPostFrameCallback((_) => afterLayoutWidgetBuild());
}
有三种可能的方法:
1) WidgetsBinding.instance.addPostFrameCallback((_) => yourFunc(context));
2) Future.delayed(Duration.zero, () => yourFunc(context));
3) Timer.run(() => yourFunc(context));
至于context
,我需要它在呈现完所有小部件后,在Scaffold.of(context)
中使用
但在我看来,最好的办法是:
void main() async {
WidgetsFlutterBinding.ensureInitialized(); //all widgets are rendered here
await yourFunc();
runApp( MyApp() );
}
如果只想这样做一次,那么就这样做,因为框架将为它创建的每个状态对象调用一次
initState()
方法
@override
void initState() {
super.initState();
WidgetsBinding.instance
.addPostFrameCallback((_) => executeAfterBuildComplete(context));
}
如果您想像在背面一样一次又一次地执行此操作,或者导航到下一个屏幕等等,那么请执行此操作,因为当此状态对象的依赖项更改时调用了didChangeDependencies()
例如,如果先前对build
的调用引用了一个后来更改的InheritedWidget
,框架将调用此方法来通知此对象此更改
此方法也会在initState
之后立即调用。从该方法调用BuildContext.dependonheritedwidgetofexacttype
是安全的
@override
void didChangeDependencies() {
super.didChangeDependencies();
WidgetsBinding.instance
.addPostFrameCallback((_) => executeAfterBuildComplete(context));
}
这是您的回调函数
executeAfterBuildComplete([BuildContext context]){
print("Build Process Complete");
}
这样做的最佳方式 1。WidgetsBinding
WidgetsBinding.instance.addPostFrameCallback((_) {
print("WidgetsBinding");
});
SchedulerBinding.instance.addPostFrameCallback((_) {
print("SchedulerBinding");
});
2。计划绑定
WidgetsBinding.instance.addPostFrameCallback((_) {
print("WidgetsBinding");
});
SchedulerBinding.instance.addPostFrameCallback((_) {
print("SchedulerBinding");
});
它可以在initState
内部调用,在构建小部件完成渲染后,这两个小部件只会被调用一次
@override
void initState() {
// TODO: implement initState
super.initState();
print("initState");
WidgetsBinding.instance.addPostFrameCallback((_) {
print("WidgetsBinding");
});
SchedulerBinding.instance.addPostFrameCallback((_) {
print("SchedulerBinding");
});
}
上述两个代码的工作原理相同,因为它们都使用类似的绑定框架。
有关差异,请查找下面的链接
另一个对我来说非常有效的解决方案是通过
Future.delayed()
包装您想要调用的函数,如下所示:
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
Future.delayed(Duration(seconds: 3), () => yourFunction());
});
}
您不太可能希望在
build
中启动登录过程。Build可以在任何时候被多次调用。看看这个:谢谢@thomas your ans对我很有帮助。我在两天前完成了这项工作,现在他们在阅读了您的ans之后也完成了这项工作。再次感谢您做得非常好,请参见@anmol.majhail回答:WidgetsBinding.instance.addPostFrameCallback(())=>yourFunciton(context))
不再工作了Hi@Thomas,它不适合我。仍然得到null异常。有什么想法吗?@anunixercoder:这取决于你的用例。有时,您应该在非initState
中调用它,例如在build
中。您应该在yourFunction
方法中调用setState
,以使其正常工作,您可以使用StatefulWidget
类来处理它的State
对象,就像无状态widget
一样,但我强烈建议不要使用它。我还没有发现任何问题,但请首先尝试实现State
object中的所有内容,Google建议在initState()上调用数据获取。因此,此解决方案没有问题,事实上这应该是公认的答案。在React中,本机数据获取可以在布局渲染之前在componentWillMount
中进行。颤振提供了更简单的解决方案initState
对于数据获取和布局渲染都是足够的,如果我们知道如何正确地进行,ComponentWillMount将很快被弃用。因此,将在安装和构造组件后执行抓取。对我来说,这不起作用,因为在initState()时,我使用SchedulerPase.idle值获取SchedulerPase。。。它实际起作用的是在build()中添加检查,请尝试以下方法:Widget build(BuildContext context){Future.delayed(Duration.zero,(){//some action on complete});return Scaffold()}代码>第二个不再工作NoSuchMethodError(NoSuchMethodError:addPostFrameCallback方法是在null上调用的。Receiver:null
@EliaWeiss-这取决于您的用例-这只是在生成后在小部件上调用函数的一种方法。典型用法将在init()中您没有编写将每个代码放在何处。在flifter的GetX框架中,首选第二种方法(在