【问题标题】:LateInitializationError: Field 'database' has not been initializedLateInitializationError:字段“数据库”尚未初始化
【发布时间】:2021-11-04 10:45:09
【问题描述】:

我正在构建一个应用程序,到目前为止一切正常。直到我点击一个调用这个 Staful Widget 的按钮:

class ToDo1 extends StatefulWidget {
  @override
  _ToDo1State createState() => _ToDo1State();
}

class _ToDo1State extends State<ToDo1> {

  var User;
  late DatabaseService database;

  Future<void> connectToFirebase() async{
    await Firebase.initializeApp();
    final FirebaseAuth auth = FirebaseAuth.instance;
    UserCredential result = await FirebaseAuth.instance.signInAnonymously();
    User = result.user;
    database = DatabaseService(User.uid);

    if (!(await database.checkIfUserExists())) {
      database.setTodo('To-Do anlegen', false);
    }
  }

  void toggleDone(String key, bool value) {
    database.setTodo(key, !value);
    }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Center(
            child: Text(
          'Stufe 1',
          style: TextStyle(
              fontStyle: FontStyle.italic,
              decoration: TextDecoration.underline),
        )),
        backgroundColor: Color.fromRGBO(35, 112, 192, 1),
      ),
      body: FutureBuilder(
        future: connectToFirebase(),
            builder: (BuildContext context, AsyncSnapshot snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            return Center(child: CircularProgressIndicator());
          } else {
            return StreamBuilder<DocumentSnapshot> (
              stream: database.getTodos(),
              builder: (context, AsyncSnapshot<DocumentSnapshot> snapshot) {
                if(!snapshot.hasData) {
                  return CircularProgressIndicator();
                } else {
                  Map<String, dynamic> items = snapshot.data!.data as Map<String, dynamic>;
                  return ListView.separated(
                      separatorBuilder: (BuildContext context, int index) {
                        return SizedBox(
                          height: 10,
                        );
                      },
                      padding: EdgeInsets.all(10),
                      itemCount: items.length,
                      itemBuilder: (BuildContext, i) {
                        String key = items.keys.elementAt(i);
                        return ToDoItem(
                          key,
                          items[key]!,
                              () => toggleDone(key, items[key]),
                        );
                      });
                }
              }
            );
          }
            },
      )
    );
  }
}

然后我遇到以下错误:

The following LateError was thrown building FutureBuilder<void>(dirty, state: _FutureBuilderState<void>#bc115):
LateInitializationError: Field 'database' has not been initialized.

这是与 firebase 交互的类:

class DatabaseService {
  final String userID;
  DatabaseService(this.userID);

  final CollectionReference userTodos =
      FirebaseFirestore.instance.collection('userTodos');

  Future setTodo(String item, bool value) async {
    return await userTodos.doc(userID).set(
      {item:value}, SetOptions(merge: true));
  }

    Future deleteTodo(String key) async {
      return await userTodos.doc(userID).update(
        {key: FieldValue.delete(),}
      );
    }

    Future checkIfUserExists() async {
    if((await userTodos.doc(userID).get()).exists) {
      return true;
    }
      else {
        return false;
      }
    }

  Stream<DocumentSnapshot> getTodos() {
    return userTodos.doc(userID).snapshots();
  }
}

我希望我已经提供了所有必要的数据,以便问题能够得到解决。如果没有,就写信给我,我会尽量把你需要的材料发给你。

【问题讨论】:

  • 我认为问题出在这一行 database = DatabaseService(User.uid);检查这是否真的有一个值。
  • 我如何检查这个? (对不起,我是新人)
  • 打印值

标签: flutter google-cloud-firestore flutter-test


【解决方案1】:

让我们试着改变这段代码

          if (snapshot.connectionState == ConnectionState.waiting) {
            return Center(child: CircularProgressIndicator());
          } else {

          if (snapshot.connectionState != ConnectionState.done) {
            return Center(child: CircularProgressIndicator());
          } else {

async.dart文件中可以看到:

/// The state of connection to an asynchronous computation.
///
/// The usual flow of state is as follows:
///
/// 1. [none], maybe with some initial data.
/// 2. [waiting], indicating that the asynchronous operation has begun,
///    typically with the data being null.
/// 3. [active], with data being non-null, and possible changing over time.
/// 4. [done], with data being non-null.
///
/// See also:
///
///  * [AsyncSnapshot], which augments a connection state with information
///    received from the asynchronous computation.
enum ConnectionState {
  /// Not currently connected to any asynchronous computation.
  ///
  /// For example, a [FutureBuilder] whose [FutureBuilder.future] is null.
  none,

  /// Connected to an asynchronous computation and awaiting interaction.
  waiting,

  /// Connected to an active asynchronous computation.
  ///
  /// For example, a [Stream] that has returned at least one value, but is not
  /// yet done.
  active,

  /// Connected to a terminated asynchronous computation.
  done,
}

如果您只与ConnectionState.waiting 比较,您将错过ConnectionState.noneConnectionState.active,因此当您在stream 中调用.todos() 时,Future 未完成,这将导致问题。

【讨论】:

  • 这完全有道理!我已经改变了它,但我仍然得到同样的错误。知道我现在能做什么吗?
【解决方案2】:

我建议你检查这个answer,他们和你有完全相同的问题:

Future Builders 甚至在获取数据之前就已构建。所以,你应该检查它是否有数据。

在该答案中,他们建议在以下情况下使用 FutureBuilder:

FutureBuilder<Position>(
            future: getInitialPosition(),
            builder: (context, snapshot) {
                if (snapshot.hasData) {
                return Map(snapshot.data);
              }else{
                return CircularProgressIndicator(); 
                //Display loading, you may adapt this widget to your interface or use some state management solution
              }
            }
        )

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-07-27
    • 2021-10-27
    • 2021-12-29
    • 2022-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多