如何使用 getx 在一个控制器中获取另一个控制器的变量

how can I get the other controller's variable inside one controller in flutter using getx

这是一个与flutter中的getx相关的问题。 我有 2 个控制器。合同控制器和通知控制器。 在 ContractsController 中,我通过调用 Api 请求将值放入观察者变量中。 我现在想要的是在另一个控制器 - NotificationController 中获取该变量的数据。 如何使用 getx 函数获取该值?

合同控制器

class ContractsController extends GetxController {
  ExpiringContractRepository _expiringContractRepository;

  final expiringContracts = <ExpiringContract>[].obs; // This is the value what I want in another controller

  ContractsController() {
    _expiringContractRepository = new ExpiringContractRepository();
  }

  @override
  Future<void> onInit() async {
    await refreshContracts();
    super.onInit();
  }

  Future refreshContracts({bool showMessage}) async {
    await getExpiringContracts();
    if (showMessage == true) {
      Get.showSnackbar(Ui.SuccessSnackBar(message: "List of expiring contracts refreshed successfully".tr));
    }
  }

  Future getExpiringContracts() async {
    try {
      expiringContracts.value = await _expiringContractRepository.getAll(); // put the value from the api
    } catch (e) {
      Get.showSnackbar(Ui.ErrorSnackBar(message: e.toString()));
    }
  }
}

expiringContracts 在 api 请求后成功更新了数据。 现在,我想在 NotificationController

中获取该值

通知控制器

class NotificationsController extends GetxController {
  final notifications = <Notification>[].obs;
  ContractsController contractsController;

  NotificationsController() {
  }

  @override
  void onInit() async {
    contractsController = Get.find<ContractsController>();
    print(contractsController.expiringContracts);  // This shows an empty list ?????  
    super.onInit();
  }

}

概述

我想到了几个解决方案:

  • 如果您只需要在实例化时完成一次,则将 expiringContracts 列表作为构造函数参数传递给 NotificationsController,或者
  • 每次 expiringContracts 更新时,使用 GetX worker 更新 NotificationsController

第一个解决方案与 GetX 无关,它只是 ContractsControllerNotificationsController 之间的异步协调,所以让我们关注第二个解决方案:GetX Workers。

详情

NotificationsController 中,创建一个将接收 expiringContracts.

的方法

类似于:

class NotificationsController extends GetxController {

  void refreshContracts(List<ExpiringContract> contracts) {
    // do something
  }

}

请注意:none 此代码已经过测试。我纯粹是在 Whosebug 上写的,所以请考虑这个伪代码。

ContractsController 中,我们将提供上述回调方法作为构造函数参数:

ContractsController 中,类似于:

class ContractsController {

  final expiringContracts = <ExpiringContract>[].obs

  final Function(List<ExpiringContract>) refreshContractsCallback;

  ContractsController(this.refreshContractsCallback);

  @override
  void onInit() {
    super.onInit();
    refreshContracts();  // do your stuff after super.onInit
    ever(expiringContracts, refreshContractsCallback);
    // ↑ contracts → refreshContractsCallback(contracts)
    // when expiringContracts updates, run callback with them
  }
}

此处 GetX ever worker 将可观察对象作为第一个参数,将函数作为第二个参数。该函数必须采用与观察到的变量匹配的类型参数,即 List<ExpiringContract>,因此 refreshContractsCallback 的类型被定义为 Function(List<ExpiringContract>).

现在,每当 ContractsController 中更新可观察对象 expiringContracts 时,将调用 refreshContractsCallback(contracts),它通过 [=31= 向 NotificationsController 提供到期合同列表].

最后在实例化两个controller的时候inside the build() method of your route/page:

NotificationsController nx = Get.put(NotificationsController());
ContractsController cx = Get.put(ContractsController(nx.refreshContracts));

事件时间表

  • NotificationsController 被创建为 nx.
  • nx.onInit()运行秒,refreshContracts()的慢调用开始
  • ContractsController 已创建,带有 nx.refreshContracts 回调
  • 您的页面正在绘制
    • nx 此时没有合同数据,所以你可能会。需要 FutureBuilderObx/ GetX + StatelessWidget 当数据最终到达时重建
  • refreshContracts() 完成时,ever 工作人员 运行s,发送合同给 nx
  • nx.refreshContracts(contracts) 是 运行,用合约做某事

备注

  • async/await 已从 nx.onInit
  • 中删除
  • ever 工作人员将在 refreshContract 完成后 运行

GetX 中有一些强大的方法。我用 Get.put 和 Get.find

解决了这个问题

这是我添加的代码。

合同控制器

class ContractsController extends GetxController {
  ExpiringContractRepository _expiringContractRepository;

  final expiringContracts = <ExpiringContract>[].obs; // This is the value what I want in another controller

  ContractsController() {
    _expiringContractRepository = new ExpiringContractRepository();
  }

  @override
  Future<void> onInit() async {
    await refreshContracts();
    super.onInit();
  }

  Future refreshContracts({bool showMessage}) async {
    await getExpiringContracts();
    if (showMessage == true) {
      Get.showSnackbar(Ui.SuccessSnackBar(message: "List of expiring contracts refreshed successfully".tr));
    }
  }

  Future getExpiringContracts() async {
    try {
      expiringContracts.value = await _expiringContractRepository.getAll(); // put the value from the API
      // ******************************** //
      Get.put(ContractsController()); // Added here
    } catch (e) {
      Get.showSnackbar(Ui.ErrorSnackBar(message: e.toString()));
    }
  }
}

通知控制器

class NotificationsController extends GetxController {
  final notifications = <Notification>[].obs;
  ContractsController contractsController;

  NotificationsController() {
  }

  @override
  void onInit() async {
    // ******************************** //
    contractsController = Get.find<ContractsController>(); // Added here.
    print(contractsController.expiringContracts);  // This shows the updated value
    super.onInit();
  }
}

终于发现GetX在flutter中的状态管理很简单但是很强大。 谢谢