Flutter Gridview 不更新来自 firebase 的值

Flutter Gridview not updating values from firebase

我是 Flutter 新手。我正在用 firebase 构建一个应用程序。在我的应用程序中,我想在 gridview 中显示产品详细信息。详细信息取自 firebase。我成功地获得了价值。但是我从 firebase 获得的值没有更新到 GridView 列表。我的代码如下所示。

AppMain.Dart

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:augr/location/LocationScreen.dart';
import 'package:cloud_firestore/cloud_firestore.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.

  MyApp({this.firestore});
  final Firestore firestore;


  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(title: 'My Shop', firestore: firestore)
    );
  }
}

class MyHomePage extends StatefulWidget {

  MyHomePage({Key key, this.title, this.firestore}) : super(key: key);
  final Firestore firestore;
  final String title;

  @override
  _MyHomePageState createState() => new _MyHomePageState(firestore: firestore);
}

class _MyHomePageState extends State<MyHomePage> {
  _MyHomePageState({this.firestore});
  final Firestore firestore;

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        appBar: new AppBar(
        iconTheme: IconThemeData(
        color: Colors.black, //change font color here
    ),
    backgroundColor: new Color(0xFFFAFAFA),
        )
            title:"title",
      body: TheGridview().build(),
    );
  }
  }

class TheGridview{
  Card makeGridCell(String name, IconData icon){
    return Card(
      elevation: 1.0,
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          mainAxisSize: MainAxisSize.min,
          verticalDirection: VerticalDirection.down,
          children: <Widget>[
            Center(child: Icon(icon)),
            Text(name)
          ],
        ),
    );
  }

  GridView build(){
    return GridView.count(
      primary: true,
      padding: EdgeInsets.all(1.0),
      crossAxisCount: 2,
      childAspectRatio: 1.0,
      mainAxisSpacing: 1.0,
      crossAxisSpacing: 1.0,

      children: createChildrenTexts(),

    /*  children: <Widget>[
        makeGridCell("Home", Icons.access_alarm)
      ],*/


    );
  }

  List<Widget> createChildrenTexts(){
    List<Widget> childrenTexts = List<Widget>();


    getProduceID().then((data){
      for(int i=0;i<data.length;i++){

         childrenTexts.add(makeGridCell(data[i].data['message'], Icons.access_alarm));
        print("data from firebase:"+data[i].data['message']);

      }
    });

    return childrenTexts;
  }

  Future<List<DocumentSnapshot>> getProduceID() async{
    QuerySnapshot querySnapshot = await Firestore.instance.collection("messages").getDocuments();
    var list = querySnapshot.documents;
    return list;
  }
}

createChildrenTexts是我想在GridView中添加项目的方法。来自 firebase 正在控制台中打印。但没有添加到列表中。我知道我想写有状态的小部件。但是我怎么写请大家帮帮我

问题是您正在尝试从 firebase 获取数据以进行构建方法调用。请记住,在反应式编程方法中,您将网络工作与构建方法分开,并将网络调用返回的数据放入状态。在每次状态更改时,框架都会重新绘制框架。

以下代码可能对您有所帮助,但我强烈建议您通读 this

  1. 在状态class

    声明一个文档变量

    var documents = [];

  2. 从 initState 函数调用 firestore 并使用 setState() 函数更新文档值

    void initState() { super.initState(); Firestore.instance.collection("messages").getDocuments().then((data){ var list = data.documents; setState((){ documents = list; }); }); }

  3. 使用 documents 变量循环并渲染数据

    List<Widget> createChildrenTexts(){
      List<Widget> childrenTexts = List<Widget>();
      for(int i=0;i<documents.length;i++){ 
        childrenTexts.add(makeGridCell(documents[i].data['message'], Icons.access_alarm));
        print("data from firebase:"+documents[i].data['message']);  
      }
      return childrenTexts;
    }
    

当我在 _MyHomePageState class 中添加 createChildrenTexts 时,我得到了答案。所以我可以从 Firestore 访问数据。我在 _MyHomePageState 中声明数组 documents 。然后还添加了一个标志 isDocLoaded 用于检查值是否已存储。我的最终代码如下所示。

  import 'dart:async';
  import 'package:flutter/material.dart';
  import 'package:augr/location/LocationScreen.dart';
  import 'package:cloud_firestore/cloud_firestore.dart';

  void main() => runApp(MyApp());

  class MyApp extends StatelessWidget {
    // This widget is the root of your application.

    MyApp({this.firestore});
    final Firestore firestore;


    @override
    Widget build(BuildContext context) {
      return MaterialApp(
          home: MyHomePage(title: 'My Shop', firestore: firestore)
      );
    }
  }

  class MyHomePage extends StatefulWidget {

    MyHomePage({Key key, this.title, this.firestore}) : super(key: key);
    final Firestore firestore;
    final String title;

    @override
    _MyHomePageState createState() => new _MyHomePageState(firestore: firestore);
  }

  class _MyHomePageState extends State<MyHomePage> {
    _MyHomePageState({this.firestore});
    final Firestore firestore;

    var documents = [];
    bool isDocLoaded=false;


    void initState() {
      Firestore.instance.collection("messages").getDocuments().then((data) async {
        var list = data.documents;
        documents = list;
        print("init state document:" +
            documents.length.toString()); // value is getting
        super.initState();
        setState(() {
          isDocLoaded = true;
          documents = list;
        });
      });
    }

    @override
    Widget build(BuildContext context) {
      return new Scaffold(
        appBar: new AppBar(
          iconTheme: IconThemeData(
            color: Colors.black, //change font color here
          ),
          backgroundColor: new Color(0xFFFAFAFA),
        )
        title:"title",
        body: isDocLoaded? TheGridview():Center(child:CircularProgressIndicator()),
      );
    }

    Widget TheGridView(){
      return GridView.count(
        primary: true,
        padding: EdgeInsets.all(1.0),
        crossAxisCount: 2,
        childAspectRatio: 1.0,
        mainAxisSpacing: 1.0,
        crossAxisSpacing: 1.0,

        children: createChildrenTexts(),

        /*  children: <Widget>[
              makeGridCell("Home", Icons.access_alarm)
            ],*/
      );
    }

    Card makeGridCell(String name, IconData icon){
      return Card(
        elevation: 1.0,
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          mainAxisSize: MainAxisSize.min,
          verticalDirection: VerticalDirection.down,
          children: <Widget>[
            Center(child: Icon(icon)),
            Text(name)
          ],
        ),
      );
    }
    List<Widget> createChildrenTexts(){
      print("createChildrenTexts:"+documents.length.toString()); // the value getting 0
      List<Widget> childrenTexts = List<Widget>();
      for(int i=0;i<documents.length;i++){
        childrenTexts.add(makeGridCell(makeGridCell(data[i].data['message'], Icons.access_alarm));
        }
            return createchildwidget;
        }
  }