Данные внутри GetxController всегда возвращают null или Empty при использовании внутри GetBuilder

Я пытаюсь получить данные из List внутри GetxController, но он продолжает возвращать null/Empty всякий раз, когда я пытаюсь получить к нему доступ внутри GetBuilder, даже если я уже присвоил ему значение. Внутри GetxController я могу распечатать значение, но когда я хочу его использовать, оно возвращает 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();
    }
  }

}

Воспроизвести:

Шаги для воспроизведения поведения:

  • Вызов функции getBanks из BankController

  • Получить банки из BankController в add_bank.dart, например БанкКонтроллер().банки

  • Распечатайте его на терминал, он возвращает пустой список

Ожидаемое поведение: После вызова функции getBanks из BankController данные назначаются List<Bank> banks = [];, затем я создаю GetBuilder внутри add_bank.dart, чтобы получить данные внутри List<Bank> banks = []; и добавить их в раскрывающийся список. В раскрывающемся списке отобразится список всех банков.

Флаттер версия:

Flutter Channel stable, v2.10.3

Getx-версия:

get: ^4.6.5

Минимальный код воспроизведения: 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(),
                            ),
                          ),
                        ),
                      ]);
                }),
          ),
        ),
      ),
    );
  }
}

Привязать контроллеры в get_init.dart:

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

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

main.dart:

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

Я спрашиваю вас, ребята, как я могу это решить. Если у вас есть какие-либо вопросы, вы можете задать их мне.

Пожалуйста, всегда включайте ваш импорт, чтобы мы точно знали, какие пакеты вы использовали! (Иногда я предполагал другой пакет, в котором использовался класс с тем же именем, и это делало мой ответ бесполезным... 😏)

Karolina Hagegård 08.10.2022 08:23
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
1
210
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вы использовали BankController на любой другой странице?

Если нет, используйте Get.put вместо Get.find: -

final BankController bankControl = Get.put(BankController());
Ответ принят как подходящий

Это немного сложно при использовании Get.lazyPut или Get.put или вместо Get.create и в зависимости от случая, в котором вы хотите, чтобы он действовал. Like Get.lazyPut не будет создавать экземпляр во время, а создаст его, когда вы вызовете Get.find.

И в вашем случае это код из вашего вопроса.

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

когда вы вызываете await BankController().getBanks();, вы буквально создаете новый экземпляр BankController, используя его конструктор. а затем в строке ниже вы создаете еще один экземпляр BankController, но с использованием инжектора зависимостей GetX (фабрика lazyPut). Таким образом, экземпляр ctn и экземпляр, созданный в этом BankController().getBanks(), — это совершенно разные экземпляры. и, очевидно, будет производить пустые банки.

Get.lazyPut или Get.put не просто сделали весь класс одноэлементным, вам нужно вызвать Get.find и использовать экземпляр из него, чтобы он действовал как один экземпляр.

Итак, в заключение ваш код должен быть таким:

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

Более подробную информацию о разнице между put, lazyPut и create можно найти здесь:

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

Есть два способа сделать это: сделать это службой или контроллером.

Сервисный подход:

class BankService extends GetxService {}

файл main.dart

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

файл add_bank_view.dart

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

Подход контроллера:

class BankController extends GetxController {}

файл add_bank_view.dart

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

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

Другие вопросы по теме