flutter云存储插件无法在第一次传递时检索

时间:2018-01-01 20:05:23

标签: flutter

我有一个非常类似于firestore示例的示例:

GoogleSignIn _googleSignIn = new GoogleSignIn(
  scopes: <String>[
    'email',
    'https://www.googleapis.com/auth/contacts.readonly',
  ],
);
final FirebaseAuth _auth = FirebaseAuth.instance;

void main() {
  final router = new Router();
  Application.router = router;
  Routes.configureRoutes(Application.router);
  runApp(
    new MaterialApp(
      title: 'My Recipts',
      home: new HomePage(),
    ),
  );
}

class HomePage extends StatefulWidget {
  @override
  State createState() => new HomePageState();
}

class HomePageState extends State<HomePage> {
  GoogleSignInAccount _currentUser;

  @override
  void initState() {
    super.initState();
    FirebaseDatabase.instance.setPersistenceEnabled(true);
    FirebaseDatabase.instance.setPersistenceCacheSizeBytes(10000000);

    _googleSignIn.signInSilently().then((account){
      account.authentication.then((authentication) async{
        final FirebaseUser user = await _auth.signInWithGoogle(
          accessToken: authentication.accessToken,
          idToken: authentication.idToken,
        );
        Application.userid = user.uid;
        Application.user = user;
        Application.account = account;
        createUserBuckets(user.uid);
      });
      setState(() {
        _currentUser = account;
      });
    });

  }


  Future<Null> _handleSignIn() async {
    try {
      final GoogleSignInAccount googleUser = await _googleSignIn.signIn();
      final GoogleSignInAuthentication googleAuth =
      await googleUser.authentication;
      final FirebaseUser user = await _auth.signInWithGoogle(
        accessToken: googleAuth.accessToken,
        idToken: googleAuth.idToken,
      );
      Application.userid = user.uid;
      createUserBuckets(user.uid);
    } catch (error) {
      print(error);
    }
  }


  Widget _buildBody(BuildContext context) {
    if (_currentUser != null) {
      return new Recieptlist();
    } else {
      return new Column(
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        children: <Widget>[
          const Text("You are not currently signed in."),
          new RaisedButton(
            child: const Text('SIGN IN'),
            onPressed: _handleSignIn,
          ),
        ],
      );
    }
  }


  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: const Text('My Recipts'),
          leading: _currentUser == null ? null : new GoogleUserCircleAvatar(
            identity: _currentUser,
          ),
      ),
      body: new ConstrainedBox(
        constraints: const BoxConstraints.expand(),
        child: _buildBody(context),
      ),
      floatingActionButton: new FloatingActionButton(
          child: new Icon(
            Icons.add,),
          onPressed: _addDocument),
    );
  }

  void _addDocument() {
    Application.router.navigateTo(context, "/new_document");
  }


}

class Recieptlist extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return new StreamBuilder<QuerySnapshot>(
        stream: Firestore.instance
            .collection('users')
            .document(Application.userid)
            .getCollection("documents")
            .snapshots,
        builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {

          if (snapshot == null || !snapshot.hasData) {
            return const Text('No documents yet');
          }
          print("snapshot has ${snapshot.data.documents.length} members");
          return new ListView(
            children: snapshot.data.documents.map((DocumentSnapshot document) {
              return new ListTile(
                title: new Text(document['id']),
              );
            }).toList(),
          );
        }
    );
  }
}

问题是,渲染的第一遍有快照null,然后它得到一个快照,hasData等于true,但它报告文件数为零,这是不正确的。

如果我再次触发渲染,通过来回导航或热重新加载,它会正确地获取数据。

3 个答案:

答案 0 :(得分:0)

尝试显式构建ListView以及使用else语句中成功获取的快照的其他任何内容。

          if (snapshot == null || !snapshot.hasData) {
            return const Text('No documents yet');}
          else{
            return new ListView(
            print("snapshot has ${snapshot.data.documents.length} members");
              children: snapshot.data.documents.map((DocumentSnapshot document) {

                     return new ListTile(
                            title: new Text(document['id']),);}).toList(),
          );
        }}

答案 1 :(得分:0)

我认为你可以通过使你的ReceiptList有状态而不是在streambuilder中构建它来解决这个问题。这是我提出的解决方案:

class Receiptlist extends StatefulWidget {
  @override
  State<_RecieptlistState> createState() => new _RecieptlistState();
}

class _RecieptlistState extends State<Receiptlist> {
  StreamBuilder _streamBuilder;
  List<DocumentSnapshot> _documents;

  @override
  void initState() {
    _streamBuilder = new StreamBuilder<QuerySnapshot>(
      stream: Firestore.instance
        .collection('users')
        .document(Application.userid)
        .getCollection("documents")
        .snapshots,
    builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {

      if (snapshot != null && snapshot.hasData) {
        setState(() {
          print("snapshot has ${snapshot.data.documents.length} members");
          _documents = snapshot.data.documents;
        });

      }
    }
  );
}

_createListViewFromData(List<DocumentSnapshot> documents) {
  return new ListView(
    children: documents.map((DocumentSnapshot document) {
      return new ListTile(
        title: new Text(document['id']),
      );
    }).toList(),
  );
}

  @override
  Widget build(BuildContext context) {
    return _documents.length > 0 ? _createListViewFromData(_documents) : const Text('No documents yet'); 
  }
}

答案 2 :(得分:0)

问题是userId应该是小部件状态的一部分。没有它,颤动并不知道它需要刷新视图。