如何在将项目插入 AnimatedList(连接到 Firebase 数据库)时修复 rangeError
How to fix rangeError during inserting item into AnimatedList (connected to Firebase database)
我正在向数据库中插入文档并更新 AnimatedList 的 GlobalKey 的 currentState,以便让它知道添加的新项目
i'm geetting rangeError
但过了一会儿小部件的重建修复了错误屏幕,我的新项目正常添加
我认为问题是从数据库获取数据没有足够的时间来更新原因,当我使用这个时:
sleep(const Duration(seconds:1));
错误没有出现
我还检查了 snapshot.data 列表中的项目数和文档数,它们在小部件构建期间不相等,这给我一个错误,但它们在重建期间相等,在错误生成之后开始
删除也是一样,但是删除的时候没有报错
这是我的代码:
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
////////////////////////////////////////////////////////////////////////
///////////////////////LIST/////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
class Item {
Item({this.name, this.icon});
Icon icon;
String name;
}
class ListScreen extends StatefulWidget {
@override
_ListScreenState createState() => _ListScreenState();
}
class _ListScreenState extends State<ListScreen> {
GlobalKey<AnimatedListState> listKey = GlobalKey<AnimatedListState>();
int id;
bool isInit = true;
var animatedList;
_addItem() {
Firestore.instance.collection('incrementID').document('IDINCREMENTATION')
.setData({'lastID':--id});
setState(() {
Firestore.instance.collection('items').document('ITEM_$id')
.setData({'name':'Item $id'});
listKey.currentState.insertItem(0);
//sleep(const Duration(seconds:1));
});
}
_removeItem(int index, DocumentSnapshot snapshot) {
setState(() {
Firestore.instance.runTransaction((Transaction transaction) async{
await transaction.delete(snapshot.reference);
});
listKey.currentState.removeItem(
index,
(context, animation) => buildItem(context, snapshot, 0, animation),
duration: const Duration(milliseconds: 100),
);
});
}
Widget buildItem(
BuildContext context, DocumentSnapshot document, int index, Animation<double> animation) {
return SizeTransition(
axis: Axis.vertical,
sizeFactor: animation,
child: SizedBox(
child: ListTile(
title: Text(document['name']),
onTap: (){
_removeItem(index, document);
},
),
),
);
}
// getting last used id
getData() async {
return await Firestore.instance.collection('incrementID').getDocuments();
}
@override
Widget build(BuildContext context) {
getData().then((val) {
id = int.parse(val.documents[0].data['lastID'].toString());
});
return Scaffold(
body: Directionality(
textDirection: TextDirection.ltr,
child: StreamBuilder(
stream: Firestore.instance.collection('items').snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData ) return const Text('Loading...');
animatedList = new AnimatedList(
key: listKey,
initialItemCount: snapshot.data.documents.length,
itemBuilder: (context, index, animation) {
return
buildItem(
context, snapshot.data.documents[index], index,
animation);
},
);
return animatedList;
},
)),
floatingActionButton: FloatingActionButton(
onPressed: _addItem,
tooltip: 'Decrement',
child: Icon(Icons.add),
),
);
}
}
你应该 await
然后 insertItem()
。
_addItem() async {
await Firestore.instance.collection('incrementID').document('IDINCREMENTATION')
.setData({'lastID':--id});
await Firestore.instance.collection('items').document('ITEM_$id')
.setData({'name':'Item $id'});
setState(() {
listKey.currentState.insertItem(0);
});
}
我正在向数据库中插入文档并更新 AnimatedList 的 GlobalKey 的 currentState,以便让它知道添加的新项目 i'm geetting rangeError
但过了一会儿小部件的重建修复了错误屏幕,我的新项目正常添加
我认为问题是从数据库获取数据没有足够的时间来更新原因,当我使用这个时:
sleep(const Duration(seconds:1));
错误没有出现
我还检查了 snapshot.data 列表中的项目数和文档数,它们在小部件构建期间不相等,这给我一个错误,但它们在重建期间相等,在错误生成之后开始 删除也是一样,但是删除的时候没有报错
这是我的代码:
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
////////////////////////////////////////////////////////////////////////
///////////////////////LIST/////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
class Item {
Item({this.name, this.icon});
Icon icon;
String name;
}
class ListScreen extends StatefulWidget {
@override
_ListScreenState createState() => _ListScreenState();
}
class _ListScreenState extends State<ListScreen> {
GlobalKey<AnimatedListState> listKey = GlobalKey<AnimatedListState>();
int id;
bool isInit = true;
var animatedList;
_addItem() {
Firestore.instance.collection('incrementID').document('IDINCREMENTATION')
.setData({'lastID':--id});
setState(() {
Firestore.instance.collection('items').document('ITEM_$id')
.setData({'name':'Item $id'});
listKey.currentState.insertItem(0);
//sleep(const Duration(seconds:1));
});
}
_removeItem(int index, DocumentSnapshot snapshot) {
setState(() {
Firestore.instance.runTransaction((Transaction transaction) async{
await transaction.delete(snapshot.reference);
});
listKey.currentState.removeItem(
index,
(context, animation) => buildItem(context, snapshot, 0, animation),
duration: const Duration(milliseconds: 100),
);
});
}
Widget buildItem(
BuildContext context, DocumentSnapshot document, int index, Animation<double> animation) {
return SizeTransition(
axis: Axis.vertical,
sizeFactor: animation,
child: SizedBox(
child: ListTile(
title: Text(document['name']),
onTap: (){
_removeItem(index, document);
},
),
),
);
}
// getting last used id
getData() async {
return await Firestore.instance.collection('incrementID').getDocuments();
}
@override
Widget build(BuildContext context) {
getData().then((val) {
id = int.parse(val.documents[0].data['lastID'].toString());
});
return Scaffold(
body: Directionality(
textDirection: TextDirection.ltr,
child: StreamBuilder(
stream: Firestore.instance.collection('items').snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData ) return const Text('Loading...');
animatedList = new AnimatedList(
key: listKey,
initialItemCount: snapshot.data.documents.length,
itemBuilder: (context, index, animation) {
return
buildItem(
context, snapshot.data.documents[index], index,
animation);
},
);
return animatedList;
},
)),
floatingActionButton: FloatingActionButton(
onPressed: _addItem,
tooltip: 'Decrement',
child: Icon(Icons.add),
),
);
}
}
你应该 await
然后 insertItem()
。
_addItem() async {
await Firestore.instance.collection('incrementID').document('IDINCREMENTATION')
.setData({'lastID':--id});
await Firestore.instance.collection('items').document('ITEM_$id')
.setData({'name':'Item $id'});
setState(() {
listKey.currentState.insertItem(0);
});
}