使用颤振从 Firebase 实时数据库中读取子节点的数量
Posted
技术标签:
【中文标题】使用颤振从 Firebase 实时数据库中读取子节点的数量【英文标题】:read number of children from the firebase realtime database using flutter 【发布时间】: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),
),
),
),
);
【问题讨论】:
【参考方案1】:由于您声明了Future<int> 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 和 ***.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...'),
)
],
),
);
,
),
),
);
【讨论】:
以上是关于使用颤振从 Firebase 实时数据库中读取子节点的数量的主要内容,如果未能解决你的问题,请参考以下文章
如何在后台监听firebase实时数据库更新事件并使用颤振自动启动应用程序(如Messenger中的调用功能)?
如何从 Firebase Firestore 获取数据并将其存储在列表中以在颤振小部件中使用?
从Firebase实时数据库读取Android数据并在RecyclerView上显示