Search code examples
fluttergoogle-cloud-firestoreflutter-getx

The following StackOverflowError was thrown building Obx(has builder, dirty, state: _ObxState#896e1): Stack Overflow


I'm using Getx package in my Flutter project, but some thing went wrong!!!

In class controller I made a stream connection with firestore to fetch data and put them in a List..

In the ui class That I want to show data in, I can call the data in ListView.builder or any thing else by using Obx, but when I try to call data in DropdownButtonFormField, using Obx or Getx widgets.. The error occurred suddenly.

When I use a none stream widget like Getbuilder the error never appers, but no data will be loaded!!

Error message:

======== Exception caught by widgets library ======================================================= The following StackOverflowError was thrown building Obx(has builder, dirty, state: _ObxState#896e1): Stack Overflow

Here is the controller class:

class AddEmployeeController extends GetxController {

final CollectionReference _villagesCollectionRef =
  FirebaseFirestore.instance.collection('Categories');

  RxList<String> villageNames = RxList([]);

@override
  void onInit() {
    super.onInit();
    villageNames.bindStream(villagesNamesList());
  }

Stream<List<String>> villagesNamesList() {
    return _villagesCollectionRef.snapshots().map((QuerySnapshot query) {
      for (var element in query.docs) {
        villageNames.add(element['name']);
      }
      return villageNames;
    });
  }

}

And Here is The class where I want to show data:

class CreateAccount extends StatelessWidget {
  CreateAccount({Key? key}) : super(key: key);

  final AddEmployeeController addEmployeeController =
      Get.put(AddEmployeeController());

  final String value = '';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: AppColors.mainColor,
        title: titleText(
          text: 'Create Account',
          size: Dimensions.font20,
        ),
        centerTitle: true,
      ),
      body: Form(
        key: addEmployeeController.formKey,
        child: Column(
          children: [
            SizedBox(height: Dimensions.height40),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Obx(
                  () => SizedBox(
                    width: Dimensions.width200,
                    child: DropdownButtonFormField(
                      focusColor: AppColors.whiteColor,
                      icon: const Icon(Icons.arrow_circle_down_rounded),
                      decoration: inputDecoration(),
                      value: addEmployeeController.startingVillageName,
                      items: addEmployeeController.villageNames
                          .map((item) => DropdownMenuItem<String>(
                                value: item,
                                child: Text(item),
                              ))
                          .toList(),
                      onChanged: addEmployeeController.changeDropdownValue(value),
                    ),
                  ),
                )
              ],
            ),
          ],
        ),
      ),
    );
  }
}

Solution

  • Finally I had reached to the solution, I change the stream properties in the controller class..

    I change it from List to List as the attached:

    Stream<List<VillageModel>> villagesNamesList() {
        return _villagesCollectionRef
            .orderBy('name', descending: false)
            .snapshots()
            .map((QuerySnapshot query) {
          vilNames.add('choose village');
          vilValue = vilNames.first;
          for (var element in query.docs) {
            vilNames.add(element['name']);
          }
          update();
          return villageModel;
        });
      }
    

    And in the ui class this is changes:

    GetBuilder<AddSubscriberController>(
                            builder: (controller) => SizedBox(
                              width: Dimensions.width300,
                              child: DropdownButtonFormField(
                                focusColor: AppColors.whiteColor,
                                icon: const Icon(Icons.arrow_circle_down_rounded),
                                decoration: inputDecoration(),
                                value: controller.vilValue,
                                items: controller.vilNames
                                    .map(
                                      (item) => DropdownMenuItem<String>(
                                        value: item,
                                        child: Center(
                                          child: titleText(
                                            text: item,
                                            size: Dimensions.font16,
                                          ),
                                        ),
                                      ),
                                    )
                                    .toList(),
                                onChanged: controller.changeVillageValue,
                              ),
                            ),
                          ),