Issue
I am building a multi-list to-do app and am using Getx with Firestore. The problem occurs when adding a new list, After adding a new list it successfully adds the list to Firestore db but the new list does not get displayed in the listview. When I print-debugged arrays
it displayed an empty list even though there were multiple lists in firestore.
ArrayController
class ArrayController extends GetxController {
RxList<ArrayModel> arrayList = <ArrayModel>[].obs;
List<ArrayModel> get arrays => arrayList.value;
@override
void onInit() {
String uid = Get.find<AuthController>().user!.uid;
arrayList.bindStream(Database().arrayStream(uid));
}
}
addArray
Future<void> addArray(String uid, String title) async {
try {
await _firestore.collection("users").doc(uid).collection("arrays").add({
'dateCreated': Timestamp.now(),
'title': title,
});
} catch (e) {
rethrow;
}
}
arrayStream
Stream<List<ArrayModel>> arrayStream(String uid) {
return _firestore
.collection("users")
.doc(uid)
.collection("arrays")
.orderBy("dateCreated", descending: true)
.snapshots()
.map((QuerySnapshot query) {
List<ArrayModel> retVal = [];
for (var element in query.docs) {
retVal.add(ArrayModel.fromDocumentSnapshot(element));
}
return retVal;
});
}
ListView
GetX<ArrayController>(
init: Get.put<ArrayController>(ArrayController()),
builder: (ArrayController arrayController) {
return ListView.separated(
shrinkWrap: true,
physics: const BouncingScrollPhysics(),
itemBuilder: (context, index) =>
GestureDetector(
onLongPress: () {
Navigator.of(context).push(
Routes.routeToArrayScreenIndex(
index));
},
onTap: () {
Navigator.of(context).push(
Routes.routeToHomeScreen(
index));
},
child: Dismissible(
key: UniqueKey(),
direction:
DismissDirection.startToEnd,
onDismissed: (_) {
HapticFeedback.heavyImpact();
arrayController.arrays
.removeAt(index);
},
child: Container(
child: Padding(
padding: const EdgeInsets.only(
right: 25.0),
child: Row(
mainAxisAlignment:
MainAxisAlignment
.spaceBetween,
children: [
Padding(
child: Text(
arrayController.arrays[index].title
style: GoogleFonts
.notoSans(
color: Colors
.white,
fontSize: 25.0),
),
),
Padding(
padding:
const EdgeInsets.only(
left: 20.0),
child: Text(
'${(arrayController.arrays[index].todos?.length)'
),
),
],
),
),
),
),
),
separatorBuilder: (_, __) => const SizedBox(
height: 15.0,
),
itemCount: arrayController.arrays.length);
},
),
ArrayModel
class ArrayModel {
String? title;
String? id;
List<Todo>? todos;
Timestamp? dateCreated;
ArrayModel({this.title, this.id, this.todos, this.dateCreated});
ArrayModel.fromDocumentSnapshot(DocumentSnapshot doc) {
title = doc["title"];
id = doc.id;
todos = doc["todos"];
dateCreated = doc["dateCreated"];
}
}
Solution
The firebase stream was returning an empty list as the todos
field was not being added to firestore
and thus resulted in a bad state element
error. Removing todos
field from the model fixed the issue.
class ArrayModel {
String? title;
String? id;
List<Todo>? todos;
Timestamp? dateCreated;
ArrayModel({this.title, this.id, this.todos, this.dateCreated});
ArrayModel.fromDocumentSnapshot(DocumentSnapshot doc) {
title = doc["title"];
id = doc.id;
todos = doc["todos"]; // not being added to firestore
dateCreated = doc["dateCreated"];
}
}
Answered By – Rohith Nambiar
Answer Checked By – Katrina (FlutterFixes Volunteer)