从firebase获取数据为空,但在热重装后工作正常

时间:2018-09-28 21:49:21

标签: firebase flutter google-cloud-firestore

从firebase获取数据后,该数据为空,但如果我进行热重装,则可以正常工作。如果我对有问题的行进行注释,则代码可以正常工作并将数据正确提交到Firebase
我尝试了许多尝试将initState设置为setState的方法,但是没有用。 我什至以为在从Firebase获取数据之前就已经完成了构建,但据我所知initState应该解决此问题。我想我在这里错过了一些东西。 :(

编辑: 这是我使用futureBuilder的新属性,仍然在数据之前加载小部件

import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter_test/flutter_test.dart';

class UnlockDoor extends StatefulWidget {
  UnlockDoorState createState() => new UnlockDoorState();
}

class UnlockDoorState extends State<UnlockDoor> {
  final formKey = GlobalKey<FormState>();
  String building;
  String room;
  String name;
  String email;
  DateTime created;
  String comment;
  String uid;

  @override
  void initState() {
    FirebaseAuth.instance.currentUser().then((FirebaseUser user) {
      this.uid = user.uid;
    });
    Firestore.instance.collection('Users').document(uid).get().then((data) {
      this.name = data['Name'];
      this.email = data['Email'];
      this.building = data['Building'];
      this.room = data['Room'];
    });
    print("uid $uid");
    super.initState();
  }

  void validateAndSubmit() async {
    created = DateTime.now();
    formKey.currentState.save();
    await Firestore.instance
        .collection('Requests')
        .document('UnlockDoor')
        .collection('UnlockDoor')
        .document()
        .setData({
      'Email': email,
      'Name': name,
      'Building': building,
      'Room': room,
      'Comment': comment,
      'Status': "Pending",
      'Created': created,
      'Housing_Emp': "",
      'UID': uid
    });
    Navigator.of(context).pop();
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("Unlock Door Request"),
      ),
      body: new FutureBuilder<DocumentSnapshot>(
        future: Firestore.instance.collection('Users').document(uid).get(),
        builder: (context, snapshot) {
          switch (snapshot.connectionState) {
            case ConnectionState.none:
            case ConnectionState.active:
            case ConnectionState.waiting:
              return Center(child: CircularProgressIndicator());
            case ConnectionState.done:
              if (snapshot.hasError) {
                return Center(child: Text('Error: ${snapshot.error}'));
              } else {
                print("why give null $name");
                return new Container(
                  padding: EdgeInsets.only(top: 60.0, left: 20.0, right: 20.0),
                  child: new Form(
                    key: formKey,
                    child: new ListView(
                      children: <Widget>[
                        Text(
                          'Requesting Door Unlock:',
                          style: TextStyle(
                            fontSize: 20.0,
                            fontWeight: FontWeight.bold,
                          ),
                        ),
                        SizedBox(height: 15.0),
                        Text(
                          "building: $building, Room: $room",
                          style: TextStyle(
                            fontSize: 15.0,
                            fontStyle: FontStyle.italic,
                          ),
                        ),
                        TextFormField(
                          maxLength: 200,
                          onSaved: (value) => comment = value,
                          decoration: InputDecoration(
                            labelText: 'Comment (optional)',
                            labelStyle: TextStyle(
                                fontSize: 18.0,
                                fontWeight: FontWeight.bold,
                                color: Colors.black54),
                          ),
                        ),
                        Container(
                          height: 50.0,
                          width: 130.0,
                          child: RaisedButton(
                              child: Text(
                                'Send Request',
                                style: TextStyle(
                                  fontSize: 15.0,
                                  fontWeight: FontWeight.bold,
                                ),
                              ),
                              splashColor: Colors.lightGreen,
                              onPressed: () {
                                _handlePressed(context);
                              }),
                        ),
                      ],
                    ),
                  ),
                );
              }
          }
        },
      ),
    );
  }

  void _handlePressed(BuildContext context) {
    confirmDialog(context).then((bool value) async {
      if (value) {
        validateAndSubmit();
      }
    });
  }
}

Future<bool> confirmDialog(BuildContext context) {
  return showDialog<bool>(
      context: context,
      barrierDismissible: false,
      builder: (BuildContext context) {
        return new AlertDialog(
          title: new Text("Send Request"),
          actions: <Widget>[
            new FlatButton(
              child: Text("Yes"),
              onPressed: () => Navigator.of(context).pop(true),
            ),
            new FlatButton(
              child: Text("No"),
              onPressed: () => Navigator.of(context).pop(false),
            ),
          ],
        );
      });
}

1 个答案:

答案 0 :(得分:2)

您正在尝试在 async 任务中获取document,并且正在view(widget)中使用该值。从 Firebase 获取document之前,文档的值为 null

可能的解决方案:

  1. 使用空检查并在小部件中处理(不推荐)
  2. 使用 FutureBuilder 非常适合您的用例。例如,refer

我编辑了您的代码。看看

class UnlockDoorState extends State<UnlockDoor> {
  final formKey = GlobalKey<FormState>();
  String building;
  String room;
  String name;
  String email;
  DateTime created;
  String comment;
  String uid;
  Future data; //changed

  @override
  void initState() {
    super.initState();
    data = getDataFromFb(); //changed
  }

  Future<void> getDataFromFb() async {  //changed
    FirebaseUser user = await FirebaseAuth.instance.currentUser();
    this.uid = user.uid;
    var data = Firestore.instance.collection('Users').document(uid).get();
    this.name = data['Name'];
    this.email = data['Email'];
    this.building = data['Building'];
    this.room = data['Room'];
    return;
  }

  void validateAndSubmit() async {
    created = DateTime.now();
    formKey.currentState.save();
    await Firestore.instance
        .collection('Requests')
        .document('UnlockDoor')
        .collection('UnlockDoor')
        .document()
        .setData({
      'Email': email,
      'Name': name,
      'Building': building,
      'Room': room,
      'Comment': comment,
      'Status': "Pending",
      'Created': created,
      'Housing_Emp': "",
      'UID': uid
    });
    Navigator.of(context).pop();
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("Unlock Door Request"),
      ),
      body: new FutureBuilder<DocumentSnapshot>(
        future: data, //changed
        builder: (context, snapshot) {
          switch (snapshot.connectionState) {
            case ConnectionState.none:
            case ConnectionState.active:
            case ConnectionState.waiting:
              return Center(child: CircularProgressIndicator());
            case ConnectionState.done:
              if (snapshot.hasError) {
                return Center(child: Text('Error: ${snapshot.error}'));
              } else {
                print("why give null $name");
                return new Container(
                  padding: EdgeInsets.only(top: 60.0, left: 20.0, right: 20.0),
                  child: new Form(
                    key: formKey,
                    child: new ListView(
                      children: <Widget>[
                        Text(
                          'Requesting Door Unlock:',
                          style: TextStyle(
                            fontSize: 20.0,
                            fontWeight: FontWeight.bold,
                          ),
                        ),
                        SizedBox(height: 15.0),
                        Text(
                          "building: $building, Room: $room",
                          style: TextStyle(
                            fontSize: 15.0,
                            fontStyle: FontStyle.italic,
                          ),
                        ),
                        TextFormField(
                          maxLength: 200,
                          onSaved: (value) => comment = value,
                          decoration: InputDecoration(
                            labelText: 'Comment (optional)',
                            labelStyle: TextStyle(
                                fontSize: 18.0,
                                fontWeight: FontWeight.bold,
                                color: Colors.black54),
                          ),
                        ),
                        Container(
                          height: 50.0,
                          width: 130.0,
                          child: RaisedButton(
                              child: Text(
                                'Send Request',
                                style: TextStyle(
                                  fontSize: 15.0,
                                  fontWeight: FontWeight.bold,
                                ),
                              ),
                              splashColor: Colors.lightGreen,
                              onPressed: () {
                                _handlePressed(context);
                              }),
                        ),
                      ],
                    ),
                  ),
                );
              }
          }
        },
      ),
    );
  }

  void _handlePressed(BuildContext context) {
    confirmDialog(context).then((bool value) async {
      if (value) {
        validateAndSubmit();
      }
    });
  }
}