【问题标题】:read number of children from the firebase realtime database using flutter使用颤振从 Firebase 实时数据库中读取子节点的数量
【发布时间】:2021-06-30 22:25:45
【问题描述】:

我是 Flutter 的新手,我真的需要帮助解决关于从 Firebase 实时数据库中读取/计算孩子数量的问题。

  • 我使用的数据库有几个类别。
  • 每个类别都有几个案例。

我想要的是从数据库中提取信息,每个类别有多少案例,并在列表中显示此信息。这意味着 - 显示类别的名称AND该类别有多少孩子(案例)(totalCases)...

这是我的代码,我正在努力:

    import '../components/category_list_tile.dart';
    import 'package:firebase_database/ui/firebase_animated_list.dart';
    import 'package:flutter/material.dart';
    import 'package:modal_progress_hud/modal_progress_hud.dart';
    import '../constants.dart';
    import 'package:firebase_core/firebase_core.dart';
    import 'package:firebase_database/firebase_database.dart';
    import 'dart:async';
    
    class ScreenCategoryList extends StatefulWidget {
      static String id = 'screen_category_list';
      final FirebaseApp app;
    
      ScreenCategoryList({this.app});
      @override
      _ScreenCategoryListState createState() => _ScreenCategoryListState();
    }
    
    class _ScreenCategoryListState extends State<ScreenCategoryList> {
      final referenceDatabase = FirebaseDatabase.instance;
      final _dbRef = FirebaseDatabase.instance.reference().child("de");
    
      static int number = 100;
      bool showSpinner = false;
      DatabaseReference _databaseReference;
    
      @override
      void initState() {
        final FirebaseDatabase database = FirebaseDatabase(app: widget.app);
        _databaseReference = database.reference().child("de");
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        return Container(
          decoration: BoxDecoration(
            gradient: LinearGradient(
              colors: [Colors.white, Colors.white],
            ),
            image: const DecorationImage(
                image: AssetImage("images/background.png"), fit: BoxFit.cover),
          ),
          child: Scaffold(
            backgroundColor: Colors.transparent,
            appBar: AppBar(
              toolbarHeight: 60.0,
              elevation: 0.0,
              backgroundColor: Colors.black12,
              leading: Padding(
                  padding: EdgeInsets.only(left: 12.0, top: 12.0, bottom: 12.0),
                  child: Image(image: AssetImage('images/lexlogo_black.png'))),
              title: Center(
                child: Column(
                  children: [
                    Text(
                      'Kategorien',
                      style: TextStyle(
                          color: kMainDarkColor,
                          fontFamily: 'Roboto',
                          fontSize: 21.0,
                          fontWeight: FontWeight.bold),
                    ),
                  ],
                ),
              ),
              actions: [
                Padding(
                  padding: EdgeInsets.only(right: 8.0),
                  child: IconButton(
                    icon: Icon(Icons.more_vert_rounded),
                    iconSize: 30.0,
                    color: kMainDarkColor,
                    onPressed: () {},
                    //onPressed: onPressMenuButton,
                  ),
                ),
              ],
            ),
            body: ModalProgressHUD(
              inAsyncCall: showSpinner,
              child: FirebaseAnimatedList(
                query: _databaseReference.child('category'),
                itemBuilder: (
                  BuildContext context,
                  DataSnapshot snapshot,
                  Animation<double> animation,
                  int index,
                ) {
                  Future<int> getNumberOfNodes() async {
                    final response = await FirebaseDatabase.instance
                        .reference()
                        .child('de')
                        .child('category')
                        .child('$index')
                        .child('cases')
                        .once();
                    var nodes = [];
                    response.value.forEach((v) => nodes.add(v));
    
                    return nodes.length;
                  }
    
                  var myNumber = getNumberOfNodes();
                  int myInt = 99;
                  myNumber.then((value) {
                    myInt = value;
                  });
                  number = myInt;
    
                  return CategoryListTile(
                    title: snapshot.value['name'].toString(),
                    successfulCases: 1,
                    totalCases: number,
                    onTitleClick: () {},
                    onInfoButtonClick: () {},
                  );
                },
                reverse: false,
                padding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 20.0),
              ),
            ),
          ),
        );
      }
    }

【问题讨论】:

    标签: firebase flutter dart firebase-realtime-database


    【解决方案1】:

    由于您声明了Future&lt;int&gt; getNumberOfNodes() async,因此您需要FutureBuilder 才能显示该值。

    类似这样的:

      child: FutureBuilder<int>(
        future: FirebaseDatabase.instance
                .reference()
                .child('de')
                .child('category')
                .child('$index')
                .child('cases')
                .once();
            var nodes = [];
            response.value.forEach((v) => nodes.add(v));
            return nodes.length;
          }
        builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
          List<Widget> children;
          if (snapshot.hasData) {
            return Text("Case count: "+snapshot.data);
          } else if (snapshot.hasError) {
            return Text('Error: ${snapshot.error}'),
          } else {
            return CircularProgressIndicator();
          }
        },
      )
    

    我没有编译或运行这段代码,所以请把它当作伪代码。如果您在使用此功能时遇到任何错误,请在反馈之前尝试通过搜索错误消息来修复它们。

    所以future 是确定值的代码,然后builder 根据值是否可用来呈现正确的UI。你会想用你自己的 UI 替换 Text("Case count: "+snapshot.data),所以 CategoryListTile(...)。

    【讨论】:

    • 您好弗兰克,感谢您的回答。正如我已经说过的,我对颤动真的很陌生。我真的不明白,如何将未来的构建器集成到我的代码中......
    • 您是否尝试包含此代码?当你这样做的时候发生了什么?您是否也阅读过FutureBuilder 的内容? api.flutter.dev/flutter/widgets/FutureBuilder-class.html 和 stackoverflow.com/questions/51983011/…
    • 是的,我做到了。我花了几乎一整天的时间尝试,但没有任何效果......我想要的是从数据库中提取信息,每个类别有多少案例并在列表中显示这些信息。这意味着 - 显示类别的名称以及该类别有多少孩子(案例)(totalCases)......在Java / Android中,我可以通过调用dataSnapshot.getChildrenCount()来获取孩子的数量。它根本不起作用。请帮忙。
    【解决方案2】:

    感谢@Frank van Puffelen 的建议。终于可以读取至少一个类别的孩子的数量了。

    必须像这样更改代码:

    class _ScreenCategoryListState extends State<ScreenCategoryList> {
      final referenceDatabase = FirebaseDatabase.instance;
    
      bool showSpinner = false;
      DatabaseReference _databaseReference;
    
      @override
      void initState() {
        final FirebaseDatabase database = FirebaseDatabase(app: widget.app);
        _databaseReference = database.reference().child("de");
        super.initState();
      }
    
      Future<Map<int, int>> getNumberOfNodes() async {
        Map<int, int> caseNumbers = new Map<int, int>();
        // read number of category nodes
        final categoriesNumbersResponse = await FirebaseDatabase.instance
            .reference()
            .child('de')
            .child('category')
            // .child('0')
            // .child('cases')
            .once();
        var categoryNodes = [];
        categoriesNumbersResponse.value.forEach((v) => categoryNodes.add(v));
        int numberOfCategories = categoryNodes.length;
    
        //read number of cases in category
        for (int i = 0; i < numberOfCategories; i++) {
          final caseResponse = await FirebaseDatabase.instance
              .reference()
              .child('de')
              .child('category')
              .child('$i')
              .child('cases')
              .once();
          var caseNodes = [];
          caseResponse.value.forEach((v) => caseNodes.add(v));
          int numberOfCases = caseNodes.length;
          caseNumbers[i] = numberOfCases;
        }
        return caseNumbers;
      }
    
      @override
      Widget build(BuildContext context) {
        return Container(
          decoration: BoxDecoration(
            gradient: LinearGradient(
              colors: [Colors.white, Colors.white],
            ),
            image: const DecorationImage(
                image: AssetImage("images/background.png"), fit: BoxFit.cover),
          ),
          child: Scaffold(
            backgroundColor: Colors.transparent,
            appBar: AppBar(
              toolbarHeight: 60.0,
              elevation: 0.0,
              backgroundColor: Colors.black12,
              leading: Padding(
                  padding: EdgeInsets.only(left: 12.0, top: 12.0, bottom: 12.0),
                  child: Image(image: AssetImage('images/lexlogo_black.png'))),
              title: Center(
                child: Column(
                  children: [
                    Text(
                      'Kategorien',
                      style: TextStyle(
                          color: kMainDarkColor,
                          fontFamily: 'Roboto',
                          fontSize: 21.0,
                          fontWeight: FontWeight.bold),
                    ),
                  ],
                ),
              ),
              actions: [
                Padding(
                  padding: EdgeInsets.only(right: 8.0),
                  child: IconButton(
                    icon: Icon(Icons.more_vert_rounded),
                    iconSize: 30.0,
                    color: kMainDarkColor,
                    onPressed: () {},
                    //onPressed: onPressMenuButton,
                  ),
                ),
              ],
            ),
            body: FutureBuilder<Map<int, int>>(
              future: getNumberOfNodes(),
              builder: (BuildContext context,
                  AsyncSnapshot<Map<int, int>> casesSnapshot) {
                if (casesSnapshot.hasData) {
                  return FirebaseAnimatedList(
                    reverse: false,
                    padding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 20.0),
                    query: _databaseReference.child('category'),
                    itemBuilder: (
                      BuildContext context,
                      DataSnapshot categorySnapshot,
                      Animation<double> animation,
                      int index,
                    ) {
                      int numberOfCases = casesSnapshot.data[index];
                      //print('number  of cases  $_counter, $numberOfCases');
                      return CategoryListTile(
                        title: categorySnapshot.value['name'].toString(),
                        successfulCases: 10,
                        totalCases: numberOfCases,
                        onTitleClick: () {},
                        onInfoButtonClick: () {},
                      );
                    },
                  );
                } else if (casesSnapshot.hasError) {
                  return Center(
                    child: Column(
                      children: <Widget>[
                        Icon(
                          Icons.error_outline,
                          color: Colors.red,
                          size: 60,
                        ),
                        Padding(
                          padding: const EdgeInsets.only(top: 16),
                          child: Text('Error: ${casesSnapshot.error}'),
                        )
                      ],
                    ),
                  );
                } else {
                  return Center(
                    child: Column(
                      children: <Widget>[
                        SizedBox(
                          child: CircularProgressIndicator(),
                          width: 60,
                          height: 60,
                        ),
                        Padding(
                          padding: EdgeInsets.only(top: 16),
                          child: Text('Awaiting result...'),
                        )
                      ],
                    ),
                  );
                }
              },
            ),
          ),
        );
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2022-06-27
      • 1970-01-01
      • 2020-02-20
      • 2020-08-20
      • 2021-08-05
      • 2019-01-01
      • 1970-01-01
      • 2021-10-16
      • 2020-09-10
      相关资源
      最近更新 更多