I'm inserting a document to a database and updating a GlobalKey's currentState of an AnimatedList in order to let it know about new item added i'm geetting rangeError
but after a few moments widget's rebuild fixes error screen and my new item add normally
I think the problem is that getting data from database have not enough time for updating cause when i'm using this:
sleep(const Duration(seconds:1));
the error doesn't appear
Also I was checking the number of items in list and number of documents of snapshot.data, they're not equal during the widget's build which give me an error, but they're equal during the rebuild, which starts just after the error's build The same is about the removing, but there's no error screen during removing
Here's my code:
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),
),
);
}
}
You should probably
await
and theninsertItem()
.