How do I make sure my batchNo gets updated for every iteration in my for loop? I am confused with the 'right' way of tackling this problem. I am guessing I am supposed to initialise batchNo locally and update it as I go instead of fetching it every time I call loadAndUploadCsvData(). I tried declaring a local _batchNo in my initState() but am unsure on how to access this variable. I tried making a localVariable within my _TestUploadState, but am unsure on how to update the variable within Widget build because it is not a future Build.
What happens: batchNo doesn't get updated each iteration in the for loop, so the data is all stored in a single document. batchNo fetches from firebase (i.e. batchNo = 1), upon the second iteration of the loop batchNo stays 1 and doesn't get updated possibly due to the lack of the await keyword.
Expected: I want batchNo to be updated each iteration in the for loop, so a seperate document is created per iteration. batchNo fetches from firebase (i.e. batchNo = 1), upon the second iteration of the loop batchNo gets updated and batchNo = 2.
class TestUpload extends StatefulWidget {
const TestUpload({super.key});
@override
_TestUploadState createState() => _TestUploadState();
}
class _TestUploadState extends State<TestUpload> {
Widget build(BuildContext context) {
// batchNo not updating within for loop
for (BatchData batchData in _batchDataList) {
loadAndUploadCsvData(batchData.name, batchData.bytes);
}
}
void loadAndUploadCsvData(String name, Uint8List? bytes) async {
// First batchNo call is not updated on subsequent batchNo
int batchNo = await getNextBatchNo();
// Send current batch to firebase
FirebaseFirestore.instance
.collection('availableBatches')
.doc("batch" "$batchNo")
.set({"batchNo": batchNo});
}
// Gets next batch no from firebase from document names
Future<int> getNextBatchNo() async {
QuerySnapshot batchCollection = await FirebaseFirestore.instance
.collection('availableBatches')
.orderBy('batchNo', descending: true)
.get();
// If collection doesn't exist
if (batchCollection.docs.isEmpty) {
return 1;
}
int batchNo = batchCollection.docs[0].get('batchNo');
return batchNo + 1;
}
}
I've tried doing this instead
class TestUpload extends StatefulWidget {
const TestUpload({super.key});
@override
_TestUploadState createState() => _TestUploadState();
}
class _TestUploadState extends State<TestUpload> {
int _batchNo = 1;
int iteration = 0;
final List<BatchData> _batchDataList = [];
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
padding: EdgeInsets.all(8),
child: Column(
children: [
const SizedBox(
height: 12,
),
ElevatedButton(
onPressed: () {
for (BatchData batchData in _batchDataList) {
loadAndUploadCsvData(batchData.name, batchData.bytes);
log("iteration: $iteration");
iteration++;
log("_batchNo: $_batchNo");
updateBatchNo();
}
},
child: Text("TESTING")),
],
)),
);
}
void loadAndUploadCsvData(String name, Uint8List? bytes) async {
String extension = name.split('.').last;
int batchNo = await getNextBatchNo();
if (extension == 'xls' || extension == "xlsx") {
// Do some xls xlsx manipulation
var excel = Excel.decodeBytes(bytes!);
for (var table in excel.tables.keys) {
for (var row in excel.tables[table]!.rows) {
ContactModel currentContact;
// Skip first (header) row
if (row[0]!.colIndex == 0 && row[0]!.rowIndex == 0) {
continue;
}
// Create currentContact Model
currentContact = ContactModel(
name: row[0]!.value,
number: row[1]!.value,
type: row[2]!.value,
isCalled: false);
// Send current batch to firebase
_firestore
.collection('availableBatches')
.doc("batch" "$batchNo")
.set({"batchNo": batchNo});
// Send current contact to firebase
_firestore
.collection('availableBatches')
.doc("batch" "$batchNo")
.collection("batchCollection")
.add(currentContact.toMap());
}
}
}
}
Future<int> getNextBatchNo() async {
QuerySnapshot batchCollection = await FirebaseFirestore.instance
.collection('availableBatches')
.orderBy('batchNo', descending: true)
.get();
// If collection doesn't exist
if (batchCollection.docs.isEmpty) {
setState(() {
_batchNo = 1;
});
return 1;
}
int batchNo = batchCollection.docs[0].get('batchNo');
setState(() {
_batchNo = batchNo + 1;
});
return batchNo + 1;
}
void updateBatchNo() async {
int batchNo = await getNextBatchNo();
setState(() {
_batchNo = batchNo;
});
}
}
But still when trying to send my details to firestore through my loop
[log] iteration: 0
[log] _batchNo: 1
[log] iteration: 1
[log] _batchNo: 1