Flutter:Widget构建完成后运行方法

Kin*_*lot 42 dart flutter

我希望能够在Widget完成构建/加载后运行函数,但我不确定如何.我目前的用例是检查用户是否经过身份验证,如果没有,则重定向到登录视图.我不想在之前检查并推送登录视图或主视图,它需要在主视图加载后发生.有什么我可以用来做这个吗?

谢谢

Tho*_*mas 80

你可以用

https://github.com/slightfoot/flutter_after_layout

在布局完成后只执行一次函数.或者只是看看它的实现并将其添加到您的代码中:-)

这基本上是

  void initState() {
    super.initState();
    WidgetsBinding.instance
        .addPostFrameCallback((_) => yourFunction(context));
  }
Run Code Online (Sandbox Code Playgroud)

  • 参见@ anmol.majhail答案:`WidgetsBinding.instance.addPostFrameCallback((_)=> yourFunciton(context));`不再起作用 (3认同)
  • @anunixercoder:这取决于您的用例。有时,您应该在“initState”以外的地方调用它,例如。在“构建”中。 (2认同)
  • 您应该在“yourFunction”方法中调用“setState”以使其正常工作 (2认同)

anm*_*ail 41

更新: Flutter v1.8.4

上面提到的两个代码现在都可以正常工作:

工作方式:

WidgetsBinding.instance
        .addPostFrameCallback((_) => yourFunction(context));
Run Code Online (Sandbox Code Playgroud)

工作中

import 'package:flutter/scheduler.dart';

SchedulerBinding.instance.addPostFrameCallback((_) => yourFunction(context));
Run Code Online (Sandbox Code Playgroud)

  • 第二个不再起作用。```NoSuchMethodError (NoSuchMethodError: 方法 'addPostFrameCallback' 被调用为 null。接收者: null``` (2认同)

小智 40

有3种可能的方式:

1) WidgetsBinding.instance.addPostFrameCallback((_) => yourFunc(context));

2) Future.delayed(Duration.zero, () => yourFunc(context));

3) Timer.run(() => yourFunc(context));
Run Code Online (Sandbox Code Playgroud)

至于context,我需要在Scaffold.of(context)我的所有小部件渲染后使用它。

但在我看来,最好的方法是这样的:

void main() async {
  WidgetsFlutterBinding.ensureInitialized(); //all widgets are rendered here
  await yourFunc();
  runApp( MyApp() );
}
Run Code Online (Sandbox Code Playgroud)

  • 在 Flutter 的 GetX 框架中,首选第二种方式(在 widget 声明内):`Future.delayed(Duration.zero, () => yourFunc(context));` (4认同)
  • 我可以确认@ConstantineKurbatov。使用 GetX 和 `WidgetsBinding` 不起作用,但会产生错误的结果和奇怪的行为。使用 `Future.delayed()` 解决了我的问题! (2认同)

jit*_*555 35

这样做的最佳方法,

1. WidgetsBinding

WidgetsBinding.instance.addPostFrameCallback((_) {
      print("WidgetsBinding");
    });
Run Code Online (Sandbox Code Playgroud)

2.调度器绑定

SchedulerBinding.instance.addPostFrameCallback((_) {
  print("SchedulerBinding");
});
Run Code Online (Sandbox Code Playgroud)

它可以在 insideinitState调用,在 Build widgets 完成渲染后只会调用一次。

@override
  void initState() {
    // TODO: implement initState
    super.initState();
    print("initState");
    WidgetsBinding.instance.addPostFrameCallback((_) {
      print("WidgetsBinding");
    });
    SchedulerBinding.instance.addPostFrameCallback((_) {
      print("SchedulerBinding");
    });
  }
Run Code Online (Sandbox Code Playgroud)

上面两个代码的工作原理相同,因为它们都使用类似的绑定框架。对于差异,请找到以下链接。

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

  • 如果它是一个“StatelessWidget”怎么办? (6认同)

jer*_*nho 12

如果你正在寻找 ReactNative 的componentDidMount等价物,Flutter 有它。这不是那么简单,但它的工作方式是一样的。在 Flutter 中,Widgets 不直接处理它们的事件。相反,他们使用他们的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);
}
Run Code Online (Sandbox Code Playgroud)

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

  • https://flutter.dev/docs/cookbook/networking/fetch-data Google 建议在 initState() 上调用数据获取。因此这个解决方案没有问题,事实上这应该是公认的答案。 (2认同)

Uch*_*dim 10

在 Flutter 1.14.6 版,Dart 28 版中。

以下是对我有用的方法,您只需要将构建方法之后想要发生的所有事情捆绑到一个单独的方法或函数中。

@override
void initState() {
super.initState();
print('hello girl');

WidgetsBinding.instance
    .addPostFrameCallback((_) => afterLayoutWidgetBuild());

}
Run Code Online (Sandbox Code Playgroud)


小智 8

PostFrameCallback 在屏幕完全绘制之前触发。因此,Devv 的上述答案对于增加屏幕绘制延迟很有帮助。

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

  • 添加例如 3 秒的问题是您实际上不知道它是否需要 3 秒!它在不同的设备上也可能有所不同!...必须有一种方法让程序本身告诉您它何时完成绘画。 (3认同)

Ale*_*ano 6

Flutter 1.2-飞镖2.2

根据官方指南和消息来源,如果您想确定还绘制了布局的最后一帧,则可以编写例如:

import 'package:flutter/scheduler.dart';

void initState() {
   super.initState();
   if (SchedulerBinding.instance.schedulerPhase == SchedulerPhase.persistentCallbacks) {
        SchedulerBinding.instance.addPostFrameCallback((_) => yourFunction(context));
   }
}
Run Code Online (Sandbox Code Playgroud)

  • 尝试以下方式: `Widget build(BuildContext context) { Future.delayed(Duration.zero,() {//完成时执行某些操作}); 返回脚手架()};` (2认同)

sou*_*dit 6

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

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


Nav*_*mar 5

尝试 SchedulerBinding,

 SchedulerBinding.instance
                .addPostFrameCallback((_) => setState(() {
              isDataFetched = true;
            }));
Run Code Online (Sandbox Code Playgroud)