我正在将我的颤振应用程序的状态管理更改为 getx,我遇到了在下拉选择后更改应用程序状态的问题

Posted

技术标签:

【中文标题】我正在将我的颤振应用程序的状态管理更改为 getx,我遇到了在下拉选择后更改应用程序状态的问题【英文标题】:I am changing the state management of my flutter app to getx and I ran into an issue with changing the state of the app after dropdown selection 【发布时间】:2021-10-27 15:57:59 【问题描述】:

我是新 getx,如果有人可以帮助我,我将不胜感激。我有一个下拉菜单,可以根据选择的下拉菜单更改屏幕的状态。它与 setstate 一起工作正常,但我想将我的应用程序的状态管理更改为 getx。 这是我的控制器:

List<String>clientType = [
    'Anonymous',
    'New',
    'Existing Client',
    if (getIt<Data>().isAdmin()) 'Existing Account',
  ].obs;

void changeClientType(String value) 
    existingAccount = false;
    if (value == 'Existing Account') 
      existingAccount = true;
      for (int i = 0; i < products.length; i++)
        if (products[i].inventoryId.isEmpty) 
          Get.snackbar(
            'Error',
            'Please note that you cannot use "Quick Add" while selling to '
                'existing accounts. All "Quick Add" items will be skipped. '
                'To undo, change "client type" back to '
                '"$clientTypeDropdownValue"',
          );
          break;
        
    
    
    if (value == 'New') 
      newPersonInputFocusNode.requestFocus();
     else 
      Get.focusScope.unfocus();
    
    clientTypeDropdownValue = value; 
    update();
  

这是用户界面屏幕:

Widget _clientTypeDropdown() 
    double options = getIt<Data>().isAdmin() ? 4 : 3;
    return DropdownSearch<String>(
      key: _clientTypeKey,
      maxHeight: (55 * options).toDouble(),
      mode: Mode.MENU,
      showSelectedItem: true,
      items: addSalesController.clientType,
      
      label: 'Select Client Type',
      onChanged: 
      (value) => addSalesController.changeClientType(value),
      
      selectedItem: addSalesController.clientTypeDropdownValue,
    );
  
  Widget _newClientInput() 
    return TextFormField(
      controller: _newClientController,
      focusNode: _newPersonInputFocusNode,
      keyboardType: TextInputType.name,
      textCapitalization: TextCapitalization.words,
      decoration: textBorder('Enter new client\'s name'),
      validator: (value) 
        String val = value.trim();
        if (val.isEmpty) return 'Enter new client\'s name';
        if (val.length > 99) return 'Maximum length (100) exceeded';
        return null;
      ,
    );
  
  Widget _existingClientDropdown() 
    return FutureBuilder<void>(
      future: _isOthersLoaded,
      builder: (BuildContext context, AsyncSnapshot<void> snapshot) 
        if (snapshot.hasError) return Message();
        if (snapshot.connectionState == ConnectionState.waiting)
          return Loading();

        double maxHeight = (_clients.length * 55).toDouble();
        bool longerThanScreen = false;
        if (maxHeight + 100 > MediaQuery.of(context).size.height) 
          longerThanScreen = true;
          maxHeight = MediaQuery.of(context).size.height - 100;
        
        return DropdownSearch<Person>(
          maxHeight: maxHeight == 0 ? 55 : maxHeight,
          mode: Mode.MENU,
          label: 'Select Client',
          items: _clients,
          onChanged: (value) => _clientNameDropdownValue = value,
          selectedItem: _clientNameDropdownValue,
          showClearButton: true,
          validator: (v) => v == null ? 'Please select client' : null,
          showSelectedItem: true,
          compareFn: (item, selectedItem) => selectedItem == item,
          emptyBuilder: (_, __) => EmptyDropdown(),
          showSearchBox: longerThanScreen,
          searchBoxDecoration: InputDecoration(
            prefixIcon: Icon(Icons.search, size: 25),
            labelText: 'Search',
            isDense: true,
            border: OutlineInputBorder(
              borderRadius: BorderRadius.circular(5),
            ),
          ),
        );
      ,
    );
  
  Widget _existingAccountDropdown() 
    return FutureBuilder<void>(
      future: _isOthersLoaded,
      builder: (BuildContext context, AsyncSnapshot<void> snapshot) 
        if (snapshot.hasError) return Message();
        if (snapshot.connectionState == ConnectionState.waiting)
          return Loading();

        double maxHeight = (_companies.length * 55).toDouble();
        bool longerThanScreen = false;
        if (maxHeight + 100 > MediaQuery.of(context).size.height) 
          longerThanScreen = true;
          maxHeight = MediaQuery.of(context).size.height - 100;
        
        return DropdownSearch<Company>(
          maxHeight: maxHeight == 0 ? 55 : maxHeight,
          mode: Mode.MENU,
          label: 'Select Account',
          items: _companies,
          onChanged: (company) => _clientAccountDropdownValue = company,
          selectedItem: _clientAccountDropdownValue,
          showClearButton: true,
          validator: (v) => v == null ? 'Please select account' : null,
          showSelectedItem: true,
          compareFn: (item, selectedItem) => selectedItem == item,
          emptyBuilder: (_, __) => EmptyDropdown(),
          showSearchBox: longerThanScreen,
          searchBoxDecoration: InputDecoration(
            prefixIcon: Icon(Icons.search, size: 25),
            labelText: 'Search',
            isDense: true,
            border: OutlineInputBorder(
              borderRadius: BorderRadius.circular(5),
            ),
          ),
        );
      ,
    );
  

欢迎所有与此问题相关的建议。谢谢

【问题讨论】:

【参考方案1】:

我也是 GetX 的新手,但我希望这会对您有所帮助。如果您想在应用中的任何位置进行更新,您应该使用 GetxBuilder 包装您的小部件。

例如:

Container(
    child: GetBuilder<ControllerClassX>(
       init: ControllerClassX(), //init this just one time in your page.
       builder: (_) => Container(...), //this part will be updated if you trigger your function what has update(); keyword.
       ),
    ),
 ),

【讨论】:

【参考方案2】:

您应该使用 Obx 或 GetBuilder 小部件包装小部件,以便在每次更改后重建小部件树。 取决于控制器中的变量,您可以使用小部件。例如对于可观察的小部件,您可以使用 Obx(),对于普通变量,您可以使用 getBuilder()。

反应变量示例:

class Controller extends GetxController
  var count = 0.obs;
  increment() => count++;


class Home extends StatelessWidget 
  @override
  Widget build(context) 
    // Instantiate your class using Get.put() to make it available for all "child" routes there.
    final Controller c = Get.put(Controller());
    return Scaffold(
      // Use Obx(()=> to update Text() whenever count is changed.
      appBar: AppBar(title: Obx(() => Text("Clicks: $c.count"))),
      ...
  

正态变量样本:

class Controller extends GetxController 
  int counter = 0;
  void increment() 
    counter++;
    update(); // use update() to update counter variable on UI when increment be called
  


// On your Stateless/Stateful class, use GetBuilder to update Text when increment be called
GetBuilder<Controller>(
  init: Controller(), 
  builder: (_) => Text(
    '$_.counter',
  ),
)

【讨论】:

以上是关于我正在将我的颤振应用程序的状态管理更改为 getx,我遇到了在下拉选择后更改应用程序状态的问题的主要内容,如果未能解决你的问题,请参考以下文章

Flutter GetX 状态管理按钮单击

当我对颤振项目进行颤振清理时出现错误

列表项的颤振状态更新

如何使 getx 颤振以移动到下一个中​​间件

如何将我的 JAVA 卡生命周期状态更改为 OP_READY?

如何将我的 python discord 机器人的状态更改为流式传输?