【问题标题】:Flutter Gridview not updating values from firebaseFlutter Gridview 不更新来自 firebase 的值
【发布时间】:2018-11-24 10:02:55
【问题描述】:

我是新来的颤振。我正在用 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 中添加项目的方法。 from firebase 正在控制台中打印。但没有添加到列表中。我知道我想写有状态的小部件。但是我怎么写请帮帮我。

【问题讨论】:

  • 为什么你的 for 循环从值 0 运行到 1 而不是 data.length ?
  • 它用于 data.length。我对此感到抱歉。我更改了代码。

标签: android ios dart flutter flutter-layout


【解决方案1】:

当我在_MyHomePageState 类中添加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;
        }
  }

【讨论】:

    【解决方案2】:

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

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

    1. 在状态类中声明一个文档变量

      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;
      }
      

    【讨论】:

    • 在 initState() 当我添加 QuerySnapshot querySnapshot = await Firestore.instance.collection("messages").getDocuments();它显示错误“'Future'类型的值不能分配给'QuerySnapshot'类型的变量”
    • 有什么解决办法吗?
    • 只能在异步函数上使用 await 关键字,而 initState 不能成为异步函数。使用getDocuments函数中的.then方法接收数据。
    • 当我使用上面的代码时。它没有进入“setState(()”。获取文档列表的“createChildrenTexts()”为零。我用 _MyHomePageState 扩展了 TheGridview 类。在 void initState() 中,它从 firebase 获取数据。
    • 我在 _MyHomePageState 中调用了 initState。
    猜你喜欢
    • 1970-01-01
    • 2021-08-20
    • 1970-01-01
    • 1970-01-01
    • 2020-07-23
    • 2020-10-18
    • 1970-01-01
    • 2018-05-07
    • 1970-01-01
    相关资源
    最近更新 更多