Home > database >  Data inside GetxController always returns null or Empty when used inside a GetBuilder
Data inside GetxController always returns null or Empty when used inside a GetBuilder

Time:10-08

I am trying to get data from a List inside a GetxController but it keeps returning null/Empty whenever i try to access it inside a GetBuilder even when i already assigned a value to it. Inside the GetxController i can print out the value but when i want to use it it returns null/Empty

class BankController extends GetxController implements GetxService {
  BankRepo bankRepo = BankRepo();
  List<Bank> banks = [];

 
  Future<void> getBanks() async {
    ResponseModel response = await bankRepo.banks();
    if (response.statusCode == 200) {
      print(banks);    // => []
      banks = (response.data as List).map((e) => Bank.fromJson(e)).toList();
      print(banks);   // => [Instance of 'Bank', Instance of 'Bank', Instance of 'Bank', Instance of 'Bank', Instance of 'Bank', .....
      update();
    }
  }

}

To Reproduce Steps to reproduce the behavior:

call the getBanks function from BankController Get banks from BankController in add_bank.dart eg BankController().banks print it to terminal, it returns empty List

Expected behavior After calling the getBanks function from BankController, a data is been assigned to List banks = [];, then i create a GetBuilder inside add_bank.dart to get the data inside List banks = []; and add them to my Dropdown. The dropdown will then display the list of all the banks

Flutter Version: Flutter Channel stable, v2.10.3

Getx Version: get: ^4.6.5

Minimal reproduce code add_bank.dart

class AddBankView extends StatefulWidget {
  const AddBankView({Key? key}) : super(key: key);

  @override
  State<AddBankView> createState() => _AddBankViewState();
}

class _AddBankViewState extends State<AddBankView> {
  Bank selectedBank = Bank(name: "Select Bank", code: "");

  @override
  void initState() {
    getBanks();
    super.initState();
  }

  getBanks() async {
    await BankController().getBanks();
    BankController ctn = Get.find<BankController>();
    print(ctn.banks); // => []
  }

  @override
  Widget build(BuildContext context) {
  
    return SafeArea(
      child: Scaffold(
        appBar: customAppbar("New Bank"),
        body: SingleChildScrollView(
          child: Padding(
            padding: const EdgeInsets.all(20.0),


            child: GetBuilder<BankController>(
                init: BankController(),
                builder: (bankController) {
                  print(bankController.banks); // => []
                  return Column(
                      crossAxisAlignment: CrossAxisAlignment.stretch,
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        
                        Container(
                          height: 50,
                          width: MediaQuery.of(context).size.width,
                          margin: const EdgeInsets.symmetric(vertical: 20),
                          child: DropdownButtonHideUnderline(
                            child: GFDropdown(
                              padding: const EdgeInsets.symmetric(vertical: 15),
                              borderRadius: BorderRadius.circular(5),
                              border: const BorderSide(
                                  color: Colors.transparent,
                                  width: 0,
                                  style: BorderStyle.none),
                              dropdownButtonColor: Colors.transparent,
                              dropdownColor:
                                  Theme.of(context).colorScheme.surface,
                              value: selectedBank,
                              icon: Icon(
                                IconlyBold.arrowDownCircle,
                                color: Theme.of(context).colorScheme.onSurface,
                                size: 22,
                              ),
                              onChanged: (value) {
                                setState(() {
                                  selectedBank = value as Bank;
                                });
                              },
                              items: bankController.banks
                                  .map((Bank value) => DropdownMenuItem<Bank>(
                                        value: value,
                                        child: CustomText(value.name,
                                            color: theme.secondary
                                                .withOpacity(0.85)),
                                      ))
                                  .toList(),
                            ),
                          ),
                        ),
                      ]);
                }),
          ),
        ),
      ),
    );
  }
}

Bind Controllers in get_init.dart

initControllers() {
  //Repositories
  Get.lazyPut(() => BankRepo());

  //Controllers
  Get.lazyPut(() => BankController());
}

main.dart

void main() async {
  initControllers();
  runApp(const MyApp());
}

Please guys how do i fix this. If you have any other questions you can ask

CodePudding user response:

Its a bit tricky when using Get.lazyPut or Get.put or instead Get.create and depending on the case that you want it to act. Like Get.lazyPut will not create the instance at the time, and will create it when you call Get.find.

And in your case, this is the code from your question.

  getBanks() async {
    await BankController().getBanks();
    BankController ctn = Get.find<BankController>();
    print(ctn.banks); // => []
  }

when you call await BankController().getBanks(); you literally create a new instance of BankController using its constructor. and then on the line below, you create another instance of BankController but using the GetX dependency injector (lazyPut factory). So the instance ctn and the instance created in this BankController().getBanks() is completely different instance. and obviously will produce empty banks.

Get.lazyPut, or Get.put didn't simply make all of the class become singleton, you have to call Get.find and use the instance from it to make it act as a single instance.

So, in conclusion, your code should be like this:

    BankController ctn = Get.find<BankController>();
    await ctn.getBanks();
    print(ctn.banks);

More detail about the difference between put, lazyPut, and create can be found here:

https://github.com/jonataslaw/getx/blob/master/documentation/en_US/dependency_management.md#differences-between-methods

CodePudding user response:

Have you used BankController in any other page?

If not, use Get.put instead of Get.find :-

final BankController bankControl = Get.put(BankController());

CodePudding user response:

There are two ways on doing this either you make it a service or a controller.

Service approach:

class BankService extends GetxService {}

main.dart file

await Get.putAsync<BankService>(() async => BankService());

add_bank_view.dart file

getBanks() async {
   final ctn = Get.find<BankService>();
   await ctn.getBanks(); 
   print(ctn.banks); // => []
}

Controller approach:

class BankController extends GetxController {}

add_bank_view.dart file

final controller = Get.put(BankController());

getBanks() async {
   await controller.getBanks(); 
   print(controller.banks); // => []
}
  • Related