【问题标题】:InitState() not finishing before Build method is called在调用 Build 方法之前 InitState() 未完成
【发布时间】:2021-06-11 15:05:06
【问题描述】:

我的 home_screen.dart 文件有问题。我 有一个名为 pullUserData() 的方法,该方法在 initState() 中调用,但在 pullUserData() 完全完成之前,home_screen.dart 中的构建方法开始。这会导致在 home_screen.dart 的 build 方法中将空值(auth 和 friendsList)发送到 NavDrawer() 和 FriendsFeed()。

如何防止在 initState() 完全完成之前在 build 方法中调用 NavDrawer() 和 FriendsFeed()?我应该使用 FutureBuilder 吗?

User_data.dart 句柄获取 auth 和 friendsList 的值。

home_screen.dart

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:mood/components/friends_feed.dart';
import 'package:mood/components/nav_drawer.dart';
import 'package:mood/services/user_data.dart';

class LandingScreen extends StatefulWidget {
  static const String id = 'landing_screen';

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

class _LandingScreenState extends State<LandingScreen> {
  FirebaseAuth auth;
  List<dynamic> friendsList;

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

  Future<void> pullUserData() async {
    UserData userData = UserData();
    await userData.getUserData();
    auth = userData.auth;
    friendsList = userData.friendsList;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      appBar: AppBar(
        title: Text('Mood'),
        centerTitle: true,
      ),
      drawer: NavDrawer(auth),
      body: FriendsFeed(friendsList),
    );
  }
}

user_data.dart

import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';

class UserData {
  final FirebaseAuth _auth = FirebaseAuth.instance;
  User _currentUser;
  String _currentUserUID;
  List<dynamic> _friendsList;

  FirebaseAuth get auth => _auth;
  User get currentUser => _currentUser;
  String get currentUserUID => _currentUserUID;
  List<dynamic> get friendsList => _friendsList;

  Future<void> getUserData() async {
    getCurrentUser();
    getCurrentUserUID();
    await getFriendsList();
  }

  void getCurrentUser() {
    _currentUser = _auth.currentUser;
  }

  void getCurrentUserUID() {
    _currentUserUID = _auth.currentUser.uid;
  }

  Future<void> getFriendsList() async {
    await FirebaseFirestore.instance
        .collection("Users")
        .doc(_currentUserUID)
        .get()
        .then((value) {
      _friendsList = value.data()["friends"];
    });
  }
}

【问题讨论】:

  • 一个futurebuilder或一个等待所有内容加载的启动画面是我认为的最佳解决方案
  • initState 不会等待 Future。您所需要的只是一个 FutureBuilder。 medium.com/nonstopio/…

标签: flutter dart asynchronous async-await


【解决方案1】:

您的代码中有几个问题,但它会起作用。

首先,如果你想在构建过程中设置好友列表的值,你必须像这样使用setState:

setState(() {
  friendsList = userData.friendsList;
});

如果你想等到 pullUserData() 完成,你正在寻找一个叫做 splash screen 的东西,但在你的问题中,你只是在等待 body正在构建,所以我建议在您的脚手架中使用 进度指示器,如下所示:

return Scaffold(
   appBar: Bars.menuAppBar('Devices'),
   drawer: DrawerMenu(),
   backgroundColor: ColorThemes.backgroundColor,
   body: _loading
       ? Center(
           child: CircularProgressIndicator(
           valueColor: new AlwaysStoppedAnimation<Color>(
               Colors.blue), //choose your own color
         ))
       : FriendsFeed(friendsList)
);

你可以看到我使用了 _loading 变量。你必须在你的 initState() 之前定义它

bool _loading = true;

然后在 pullUserData() 函数内设置 friendsList 后,在 setState 内将 _loading 更改为 false strong> 就像这样:

setState(() {
  friendsList = userData.friendsList;
  _loading = false;
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多