FutureBuilder 运行两次

i6x*_*x86 10 dart flutter

我在 FutureBuilder 启动两次时遇到问题。首先它正确获取数据,返回我的 StartScreen,然后几秒钟后,StartScreen 重建,我注意到 FutureBuilder 再次触发。

这是我的代码,它非常简单,所以我想知道可能是什么问题?!?

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  FirebaseUser user;

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    getNewestlocation();
  }

  @override
  void dispose() {
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'APP',
      theme: buildTheme(),
      home: FutureBuilder<FirebaseUser>(
        future: Provider.of<AuthService>(context).getUser(),
        builder: (context, AsyncSnapshot<FirebaseUser> snapshot) {
          if (snapshot.connectionState == ConnectionState.done) {
            if (snapshot.error != null) {
              print('error');
              return Text(snapshot.error.toString());
            }
            user = snapshot.data;
            print('user here $user');
            return snapshot.hasData ? StartScreen(user) : LoginScreen();
          } else {
            return LoadingCircle();
          }
        },
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

任何人都可以帮我解决这个问题吗?

Alf*_*gle 19

未来再次被触发,因为您在构建方法中与 FutureBuilder 同时创建它。

来自FutureBuilder 文档

未来必须更早获得,例如在 State.initState、State.didUpdateConfig 或 State.didChangeDependencies 期间。在构造 FutureBuilder 时,它不能在 State.build 或 StatelessWidget.build 方法调用期间创建。如果future和FutureBuilder同时创建,那么每次重建FutureBuilder的parent时,异步任务都会重新启动。

所以为了防止它被触发,你必须做这样的事情:

    class _MyAppState extends State<MyApp> {
      Future<String> _myString;

      @override
      void initState() {
        super.initState();
        _myString = _fetchString();
      }

      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: FutureBuilder(
            future: _myString,
            builder: (context, snapshot) {
              // build page stuff...
            },
          ),
        );
      }
    }

    Future<String> _fetchString() async {
      print('running future function');
      await Future.delayed(Duration(seconds: 3));
      return 'potatoes';
    }
Run Code Online (Sandbox Code Playgroud)

请注意,要访问 initState() 中的提供程序,您必须将 listen 设置为 false,如答案中所述。

  • 如果我们使用无状态小部件,有什么方法可以解决这个问题吗? (2认同)

小智 -4

我认为你的代码中有一些不好的东西,也许这不是问题,但最好纠正它:首先:不建议在主文件中完成这项工作,你应该有一个类似启动页面的东西来处理它。第二:你应该使用块,而不是在视图(UI)的同一位置编写逻辑代码

  • 好吧,感谢您的建议,但您应该像评论一样发布它,因为它没有回答问题。 (5认同)