Get controller variable returns empty list

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)

Leave a Reply

Your email address will not be published. Required fields are marked *