StateNotifierProvider 不使用 HookWidget

时间:2021-07-28 19:31:28

标签: flutter dart riverpod flutter-hooks

我正在尝试使用 Riverpod 状态管理。我有两个 TextFormField,我想通过使用 Text 取每个字段中输入的值的总和来设置 StateNotifierProvider 的值。

在以下代码中,CashCounterData 是由 StateNotifierCashCounter 使用的数据模型。通知程序有两个方法,setCountsetCash,它们在每个 onChangedTextFormField 方法中调用。

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);
}

接下来,我实现了用户界面,并尝试结合上面定义的 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)),
            )
          ],
        ),
      ),
    );
  }
}

我缺少什么才能获得所需的行为?

1 个答案:

答案 0 :(得分:1)

您正在查看通知程序,而不是状态。状态会发生变化,因此会通知侦听器。

如果你只是改变它应该可以工作:

final cashCounterProvider = useProvider(cashProvider.notifier);

到:

final cashCounterProvider = useProvider(cashProvider);

然后,在您的更改处理程序中:

onChanged: (value) => context.read(cashProvider.notifier).setCash(int.tryParse(value) ?? 0),

在这样的处理程序中使用提供程序时,更喜欢上面演示的 context.read 而非 avoid unnecessary rebuilds

如果您将 TextEditingControllers 放在 build 方法中,您还需要使用钩子。

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),
            )
          ],
        ),
      ),
    );
  }
}