firebase - 如何在颤动中更改 StreamBuilder 中特定切换开关的状态
问题描述
我正在使用 Flutter 构建一个学校服务跟踪应用程序。由于我是移动应用程序开发的新手,我面临着很多错误。其中之一是,
用户登录到应用程序后,在仪表板中,它将在卡片小部件中显示其孩子的个人资料。每个配置文件都作为一个切换开关按钮来更新他们的出勤率。
每当他们点击开关按钮时,数据库中的数据就会更新。但不知道如何更改轻按的切换开关按钮的状态。
我正在使用 Google Firebase Firestore 数据库。
这是我的数据库结构。
Profiles(Children) 表结构。
以下是出勤表结构。每个文档将每天以特定日期的名称创建。在每个文档配置文件中,ids 存储为子集合。
在每个配置文件子集合中,一个文档将在配置文件名称下包含出勤详细信息。
这就是我从数据库中检索数据的方式。
CustomScrollView(
slivers: <Widget>[
SliverList(
delegate: SliverChildListDelegate([
whiteLogo(), // this is a logo widget
]),
),
StreamBuilder(
stream: Firestore.instance.collection('profiles').snapshots(),
builder: (context, snapshot) => SliverList(
delegate: SliverChildBuilderDelegate((context, index) =>
Container(
child: userCard(context, snapshot.data.documents[index]), // profile card
),
childCount: snapshot.hasData ? snapshot.data.documents.length : 0,
),
)
)
],
)
以下是 userCard 小部件
userCard(BuildContext context, DocumentSnapshot document) {
var attendanceCollection = Firestore.instance.collection('attendance').document('10-01-2019').collection(document.documentID);
var documentId = document["name"].toString().toLowerCase();
var attendanceReference = attendanceCollection.document(documentId);
bool status = true;
return Card(
margin: EdgeInsets.fromLTRB(20.0, 20.0, 20.0, 20.0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(10.0)),
),
elevation: 0.3,
color: Colors.white,
child: Padding(
padding: EdgeInsets.fromLTRB(5.0, 15.0, 5.0, 10.0),
child: Column(
children: <Widget>[
ListTile(
leading: (
Container(
width: 50.0,
height: 50.0,
decoration: BoxDecoration(
shape: BoxShape.circle,
image: DecorationImage(
fit: BoxFit.cover,
image: NetworkImage(
'${document['avatar']}'
)
),
),
)
),
title: Text(document['name']),
trailing: Column(
children: <Widget>[
Text(
'Absent/Present',
style: TextStyle(
color: Color(0xff868686),
fontSize: 12.0
),
),
Switch(value: status, onChanged: (value) {
setState(() {
status = value;
});
//onChange the "attendance_status" value is changing
Firestore.instance.runTransaction((transaction) async {
DocumentSnapshot freshSnap = await transaction.get(attendanceReference);
await transaction.update(freshSnap.reference, {
"attendance_status": value
});
});
},)
],
),
),
horizontalLine(),
textTile('School', 'Class', 13.0, Color(0xff827f7f)),
Container(margin: EdgeInsets.only(bottom: 10.0)),
textTile(document['destination'], document['class'], 16.0, Color(0xff424242)),
horizontalLine(),
buttonWrap(context, document)
],
),
),
);
}
这是仪表板的预览。
当我点击切换开关按钮时,它会更新数据库中的值。但不是按钮的状态。按钮状态没有改变。
我通过将status
变量放在 中进行测试initState
,但是状态正在影响所有按钮。
当用户点击它时,我想更改特定切换开关按钮的状态。任何帮助将非常感激。
initState() {
status = true;
super.initState();
}
解决方案
在您当前的实现中,开关状态没有反映数据库的值,因为没有订阅正在更新其值的数据。您可以使UserCard
小部件无状态,而只需使用 a 读取Switch
来自出席集合的值StreamBuilder
。
false
这样的事情应该可以解决问题,您的考勤开关将根据考勤文档设置其状态(如果尚未创建文档,则应设置为)
Column(
children: <Widget>[
Text(
'Absent/Present',
style: TextStyle(
color: Color(0xff868686),
fontSize: 12.0
),
),
StreamBuilder(
stream: attendanceReference.snapshots(),
initialData: null,
builder: (ctx, snap) {
return Switch(
value: snap.data == null ? false : snap.data["attendance_status"],
onChanged: (value) {
Firestore.instance.runTransaction((transaction) async {
DocumentSnapshot freshSnap = await transaction.get(attendanceReference);
await transaction.update(freshSnap.reference, {
"attendance_status": value
});
});
},
);
},
)
推荐阅读
- javascript - 仅在使用 javascript 过滤结果后显示引导表
- sql - SQL。大查询。从对应于另一列的数组中查找值
- node.js - 如何在 Sequelize 中插入相关实体
- makefile - 如何在 Redhawk sdr 源代码中包含新的 idl 文件并编译它们
- url - URL 路径和查询组合的命名约定
- python - 计算python对每日股价数据的相对表现
- .net - Microsoft.AnalysisServices.Tabular.JsonScripter 指的是不存在的 Json 程序集版本
- python - 4.6 之前的 pytest 能够从与已安装的命名空间包同名的本地包中导入,但现在不能。那是一个错误吗?
- javascript - 使用任何应用程序访问漫游文件夹时,访问被拒绝错误
- reactjs - 不小心删除了package.json,请问有没有办法重新生成呢?