請幫我。我想在卡片中顯示串列視圖的總專案。基本上,首先它將顯示所有 3 個類別。如果您單擊其中一個類別,它將顯示所有專案串列。所以,我要解決的問題是根據類別顯示專案的總數。
下面的編碼我嘗試使用 .length 和 List 但它沒有顯示我注冊的專案總數。
class CaseListCategory extends StatefulWidget {
const CaseListCategory ({Key? key}) : super (key : key);
@override
_CaseListCategoryState createState() => _CaseListCategoryState();
}
class _CaseListCategoryState extends State<CaseListCategory> {
@override
Widget build(BuildContext context) {
final docCase = FirebaseFirestore.instance.collection('cases').doc();
List<CriticalCaseList> cases = [];
return Scaffold(
body: Container(
padding: EdgeInsets.all(10),
child: ListView(
children: <Widget>[
GestureDetector(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => CriticalCaseList(),
),
);
},
child: Card(
elevation: 10,
color: Colors.red,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 30, horizontal: 10),
child: Container(
child: Column(
children: [
Text(
'CRITICAL',
style: TextStyle(letterSpacing: 1.0,fontSize: 20, fontWeight: FontWeight.bold),
),
Text(
"${cases.length}",
style: TextStyle(letterSpacing: 1.0,fontSize: 20, fontWeight: FontWeight.bold),
),
],
),
),
),
),
),
GestureDetector(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => ModerateCaseList(),
),
);
},
child: Card(
elevation: 10,
color: Colors.orange,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 30, horizontal: 10),
child: Column(
children: [
Text(
"MODERATE",
style: TextStyle(letterSpacing: 1.0,fontSize: 20, fontWeight: FontWeight.bold),
),
Text(
"${cases.length}",
style: TextStyle(letterSpacing: 1.0,fontSize: 20, fontWeight: FontWeight.bold),
),
],
),
),
),
),
GestureDetector(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => LowCaseList(),
),
);
},
child: Card(
elevation: 10,
color: Colors.yellow,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 30, horizontal: 10),
child: Column(
children: [
Text(
'LOW',
style: TextStyle(letterSpacing: 1.0,fontSize: 20, fontWeight: FontWeight.bold),
),
Text(
"${cases.length}",
style: TextStyle(letterSpacing: 1.0,fontSize: 20, fontWeight: FontWeight.bold),
),
],
),
),
),
),
],),
)
);
}
}
這是我點擊卡片后的頁面編碼。它顯示所有專案
類別頁面 專案頁面串列
class CriticalCaseList extends StatefulWidget {
const CriticalCaseList ({Key? key}) : super (key : key);
@override
_CriticalCaseListState createState() => _CriticalCaseListState();
}
class _CriticalCaseListState extends State<CriticalCaseList> {
User? user = FirebaseAuth.instance.currentUser;
final CollectionReference _cases = FirebaseFirestore.instance.collection('cases');
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("Critical Case"),
backgroundColor: Colors. redAccent,
centerTitle: true,
leading: IconButton(
icon: const Icon(Icons.arrow_back),
color: Colors.white,
iconSize: 30,
onPressed: () => Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (context) => const VolunteerPage())),
),
),
// Using StreamBuilder to display all products from Firestore in real-time
body: StreamBuilder(
stream: _cases.snapshots(),
builder: (context, AsyncSnapshot<QuerySnapshot> streamSnapshot) {
if (streamSnapshot.hasData) {
return ListView.builder(
itemCount: streamSnapshot.data!.docs.length,
itemBuilder: (context, index) {
final DocumentSnapshot documentSnapshot = streamSnapshot.data!.docs[index];
if(documentSnapshot['priority'] == "Critical" && documentSnapshot['status'] == "Waiting for rescue"){
return Card(
child: ListTile(
title: Text(documentSnapshot['name']),
subtitle: Text(documentSnapshot['priority'].toString()),
trailing: Icon(Icons.arrow_forward),
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => CaseListView(cid: documentSnapshot['cid']))
);
},
)
);
}
return Card();
},
);
}
return const Center(
child: CircularProgressIndicator(),
);
},
),
);
}
}
uj5u.com熱心網友回復:
問題
代碼有兩個問題。
在中,documentSnapshot 是一個快照,而不是檔案資料本身,因此您需要在呼叫documentSnapshot
CriticalCaseList后從中訪問資料。.data()在
CaseListCategory,cases.length中不起作用,因為沒有cases從 Firestore 填充的代碼部分。使用它是不合適的,
cases.length因為cases它將包含所有案例的總數(無論它們的類別如何)。但是您需要關鍵、中等或低類別的單獨總數。
解決方案
因此CriticalCaseList,更改以下行
final DocumentSnapshot documentSnapshot = streamSnapshot.data!.docs[index];
至
final DocumentSnapshot documentSnapshot = streamSnapshot.data!.docs[index].data();
(注意 .data() 附加在末尾)
鑒于您要顯示每個類別中的案例總數,您可以做的是跟蹤每個類別的總數。
因此,您可以為每個變數設定變數。然后在 中初始化它們的值initState。并且仍然在initState,您可以.snapshots().listen()在案例的集合參考上使用。這樣,每次添加或洗掉案例時,CaseListCategory小部件都會更新每個案例的總數并顯示當前總數。另外,請記住取消 中的 StreamSubscription dispose()。
最后,在顯示總計的代碼部分中cases.length,您使用給定類別的總計,而不是使用 。以下應該有效:
import 'dart:async';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'critical_case_list.dart';
import 'moderate_case_list.dart';
import 'low_case_list.dart';
class CaseListCategory extends StatefulWidget {
const CaseListCategory({Key? key}) : super(key: key);
@override
_CaseListCategoryState createState() => _CaseListCategoryState();
}
class _CaseListCategoryState extends State<CaseListCategory> {
double _criticalCases = 0, _moderateCases = 0, _lowCases = 0;
late StreamSubscription _listener;
@override
void initState() {
super.initState();
_listener = FirebaseFirestore.instance
.collection('cases')
.snapshots()
.listen((snap) {
final cases = snap.docs.map((doc) => doc.data());
_criticalCases = 0;
_moderateCases = 0;
_lowCases = 0;
for (var caseData in cases) {
if (caseData['priority'] == 'Critical') _criticalCases ;
if (caseData['moderate'] == 'Moderate') _moderateCases ;
if (caseData['low'] == 'Low') _lowCases ;
}
setState(() {});
});
}
@override
void dispose() {
_listener.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
padding: EdgeInsets.all(10),
child: ListView(
children: <Widget>[
GestureDetector(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => CriticalCaseList(),
),
);
},
child: Card(
elevation: 10,
color: Colors.red,
child: Padding(
padding:
const EdgeInsets.symmetric(vertical: 30, horizontal: 10),
child: Container(
child: Column(
children: [
Text(
'CRITICAL',
style: TextStyle(
letterSpacing: 1.0,
fontSize: 20,
fontWeight: FontWeight.bold),
),
Text(
'$_criticalCases',
style: TextStyle(
letterSpacing: 1.0,
fontSize: 20,
fontWeight: FontWeight.bold),
),
],
),
),
),
),
),
GestureDetector(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => ModerateCaseList(),
),
);
},
child: Card(
elevation: 10,
color: Colors.orange,
child: Padding(
padding:
const EdgeInsets.symmetric(vertical: 30, horizontal: 10),
child: Column(
children: [
Text(
"MODERATE",
style: TextStyle(
letterSpacing: 1.0,
fontSize: 20,
fontWeight: FontWeight.bold),
),
Text(
'$_moderateCases',
style: TextStyle(
letterSpacing: 1.0,
fontSize: 20,
fontWeight: FontWeight.bold),
),
],
),
),
),
),
GestureDetector(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => LowCaseList(),
),
);
},
child: Card(
elevation: 10,
color: Colors.yellow,
child: Padding(
padding:
const EdgeInsets.symmetric(vertical: 30, horizontal: 10),
child: Column(
children: [
Text(
'LOW',
style: TextStyle(
letterSpacing: 1.0,
fontSize: 20,
fontWeight: FontWeight.bold),
),
Text(
'$_lowCases',
style: TextStyle(
letterSpacing: 1.0,
fontSize: 20,
fontWeight: FontWeight.bold),
),
],
),
),
),
),
],
),
));
}
}
更好的解決方案
您當前的設定很昂貴。或者更確切地說,隨著您的應用程式的增長或擴展,這將是昂貴的。Firebase 會針對您閱讀的每份檔案向您收費。也就是說,每次CaseListCategory加載時,Firestore 都會讀取案例集合中的所有檔案。每次創建、更新或洗掉該集合中的任何檔案時,Firestore 都會再次獲取所有檔案(以更新總數)。
降低此類成本的一種常見模式是使用counters集合。在其中,您將擁有每個類別的檔案,這些檔案可能具有一個總屬性,其中包含給定類別的當前總數。
然后在創建或洗掉案例時增加或減少給定類別的當前計數。運行此邏輯的更好位置是在 Cloud Functions 中,您可以確定代碼會在其中運行。不建議更新客戶端中的計數,因為客戶端的網路可能會出現故障或出于安全原因。
因此,您可以在檔案中的云函式中有以下代碼index.js。
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
const db = admin.firestore();
exports.incrementCaseCount = functions.firestore
.document('/cases/{caseId}')
.onCreate(async (snap, _) => {
const category = snap.data()['priority'].toLowerCase();
await db
.doc(`/counters/${category}Cases`)
.set({ total: admin.firestore.FieldValue.increment(1) }, { merge: true })
.catch((error) => console.error(error));
});
exports.decrementCaseCount = functions.firestore
.document('/cases/{caseId}')
.onDelete(async (snap, _) => {
const category = snap.data()['priority'].toLowerCase();
await db
.doc(`/counters/${category}Cases`)
.set({ total: admin.firestore.FieldValue.increment(-1) }, { merge: true })
.catch((error) => console.error(error));
});
然后在flutter中,在initStateof中,你可以只聽countersCaseListCategory集合的快照,而不是聽整個cases集合的snapshot 。counters集合將包含少量檔案,因此從它們中讀取比讀取case集合中的所有檔案更便宜。
所以你可以在initState.
_listener = FirebaseFirestore.instance
.collection('counters')
.snapshots()
.listen((snap) {
for (var doc in snap.docs) {
if (doc.id == 'criticalCases') _criticalCases = doc.data()['total'];
if (doc.id == 'moderateCases') _moderateCases = doc.data()['total'];
if (doc.id == 'lowCases') _lowCases = doc.data()['total'];
}
setState(() {});
});
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/492814.html
