我正在将我的颤振应用程序的状态管理更改为 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,我遇到了在下拉选择后更改应用程序状态的问题的主要内容,如果未能解决你的问题,请参考以下文章