我想能够运行函数一旦一个小部件已经完成构建/加载,但我不确定如何。

我目前的用例是检查用户是否通过身份验证,如果没有,则重定向到登录视图。我不想检查之前,并推动登录视图或主视图,它需要发生后,主视图已加载。

有什么我可以用的吗?


当前回答

尝试SchedulerBinding,

 SchedulerBinding.instance
                .addPostFrameCallback((_) => setState(() {
              isDataFetched = true;
            }));

其他回答

有三种可能的方法:

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() );
}

PostFrameCallback在屏幕完全绘制之前触发。因此,Devv上面的回答有助于添加延迟以允许屏幕绘制。

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_) {
       Future.delayed(Duration(seconds: 3), () => yourFunction());
    });
  }

最好的方法是,

1. WidgetsBinding

WidgetsBinding.instance.addPostFrameCallback((_) {
      print("WidgetsBinding");
    });

2. SchedulerBinding

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");
    });
  }

以上两个代码的工作原理是一样的,因为它们都使用了类似的绑定框架。 要了解差异,请查看下面的链接。

https://medium.com/flutterworld/flutter-schedulerbinding-vs-widgetsbinding-149c71cb607f

如果你有问题与新的SDK和旧的答案,你可以尝试我的解决方案。我已经在v3.0.4上测试了它

WidgetsBinding.instance.endOfFrame.then(
  (_) {
    if (mounted) {
          // do some suff 
          // you can get width height of specific widget based on GlobalKey
       };
  },
);

如果你正在寻找ReactNative的componentDidMount等效,Flutter有它。事情没那么简单,但原理是一样的。在Flutter中,小部件不直接处理它们的事件。相反,它们使用State对象来执行此操作。

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);
}

状态。一旦屏幕完成布局渲染,initState将立即被调用。如果处于调试模式,即使在热重载时也不会再次调用,直到显式地达到这样做的时间。