我正在尝试使用Riverpod
状态管理。我有两个TextFormField
,我想通过使用StateNotifierProvider
在每个字段中输入的值的总和来设置Text
的值。
在下面的代码中,CashCounterData
是StateNotifier
、CashCounter
使用的数据模型。通知器有两个方法,setCount
和setCash
,分别在每个TextFormField
的onChanged
方法中调用。
final cashProvider = StateNotifierProvider<CashCounter, CashCounterData>((ref) => CashCounter());
class CashCounter extends StateNotifier<CashCounterData> {
CashCounter() : super(_initialData);
static const _initialData = CashCounterData(0, 0);
void setCount(int value){
state = CashCounterData(value, state.cash);
}
void setCash(value){
state = CashCounterData(state.count, value);
}
int get count => state.count;
int get cash => state.cash;
}
class CashCounterData {
final int count;
final int cash;
const CashCounterData(this.count, this.cash);
}
接下来,我实现了UI,并尝试在上面定义的StateNotifierProvider
中绑定。但是,当我在每个TextFormField
中输入值时,Text
小部件总是显示0
。
class CalculatableTextFormField extends HookWidget {
@override
Widget build(BuildContext context) {
final cashCounterProvider = useProvider(cashProvider.notifier);
final TextEditingController _count = TextEditingController();
final TextEditingController _cash = TextEditingController();
return Scaffold(
body: Form(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'${cashCounterProvider.count + cashCounterProvider.cash}'
),
TextFormField(
controller: _count,
keyboardType: TextInputType.number,
onChanged: (value)=>cashCounterProvider.setCount(int.parse(value)),
),
TextFormField(
controller: _cash,
keyboardType: TextInputType.number,
onChanged: (value)=>cashCounterProvider.setCash(int.parse(value)),
)
],
),
),
);
}
}
为了得到我想要的行为,我错过了什么?
您正在查看通知器,而不是状态。状态是被改变的,因此会通知侦听器。
只要修改:
就可以了final cashCounterProvider = useProvider(cashProvider.notifier);
:
final cashCounterProvider = useProvider(cashProvider);
然后,在您的更改处理程序中:
onChanged: (value) => context.read(cashProvider.notifier).setCash(int.tryParse(value) ?? 0),
当在这样的处理程序中使用提供者时,首选context.read
,以避免不必要的重建。
你还需要使用钩子,如果你把你的TextEditingControllers在构建方法。
final TextEditingController _count = useTextEditingController();
final TextEditingController _cash = useTextEditingController();
总之,你的解决方案如下:
class CalculatableTextFormField extends HookWidget {
@override
Widget build(BuildContext context) {
final cashCounterProvider = useProvider(cashProvider);
final TextEditingController _count = useTextEditingController();
final TextEditingController _cash = useTextEditingController();
return Scaffold(
body: Form(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('${cashCounterProvider.count + cashCounterProvider.cash}'),
TextFormField(
controller: _count,
keyboardType: TextInputType.number,
onChanged: (value) =>
context.read(cashProvider.notifier).setCount(int.tryParse(value) ?? 0),
),
TextFormField(
controller: _cash,
keyboardType: TextInputType.number,
onChanged: (value) =>
context.read(cashProvider.notifier).setCash(int.tryParse(value) ?? 0),
)
],
),
),
);
}
}