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

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

有什么我可以用的吗?


当前回答

如果你不想使用WidgetsBinding或SchedulerBinding:

使用Future或Timer(简单) Future<void> _runsAfterBuild() async { //此代码在build… } @override 小部件构建(BuildContext上下文){ 未来(_runsAfterBuild);// <——使用Future或Timer 返回容器(); } 等待一个虚拟的未来 Future<void> _runsAfterBuild() async { 等待未来((){});// <——虚拟等待 //此代码在build… } @override 小部件构建(BuildContext上下文){ _runsAfterBuild (); 返回容器(); }

其他回答

有三种可能的方法:

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

我的英语很差 原谅我

import 'package:flutter/material.dart';

class TestBox extends StatefulWidget {
  final Color color;
  final Duration delay;

  const TestBox({
    Key? key,
    this.color = Colors.red,
    this.delay = const Duration(seconds: 5),
  }) : super(key: key);

  @override
  _TestBoxState createState() => _TestBoxState();
}

class _TestBoxState extends State<TestBox> {
  String? label;

  @override
  void initState() {
    initialMembers();
    super.initState();
  }

  void initialMembers() async {
    label = await fetchLabel();

    if (mounted) setState(() {});

    /// don't worry
    /// if `(!mounted)`, means wen `build` calld
    /// the label already has the newest value
  }

  Future<String> fetchLabel() async {
    await Future.delayed(widget.delay);
    print('fetchLabel call');
    return 'from fetchLabel()';
  }

  @override
  Widget build(BuildContext context) {
    return AnimatedContainer(
      margin: EdgeInsets.symmetric(vertical: 12),
      duration: Duration(milliseconds: 500),
      width: 220,
      height: 120,
      color: label == null ? Colors.white : widget.color,
      child: Center(
        child: Text(label ?? 'fetching...'),
      ),
    );
  }
}

Column(
  children: [
    TestBox(
      delay: Duration(seconds: 1),
      color: Colors.green,
    ),
    TestBox(
      delay: Duration(seconds: 3),
      color: Colors.yellow,
    ),
    TestBox(
      delay: Duration(seconds: 5),
      color: Colors.red,
    ),
  ],
),

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

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

你可以用

https://github.com/slightfoot/flutter_after_layout

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

基本上就是

  void initState() {
    super.initState();
    WidgetsBinding.instance
        .addPostFrameCallback((_) => yourFunction(context));
  }

如果你正在寻找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将立即被调用。如果处于调试模式,即使在热重载时也不会再次调用,直到显式地达到这样做的时间。