StateNotifierProvider 只改变一次

StateNotifierProvider only wach changes once

在我关于 的最后一个问题中,我计算两个 TextFormField 的问题已经解决,现在我不再使用 HookWidget,而是尝试使用 ConsumerWidget 来实现它。我将我最后的代码迁移到:

class CalculateTextFormField extends ConsumerWidget {
  @override
  Widget build(BuildContext context,ScopedReader watch) {
    final cashCounterProvider = watch(cashProvider);
    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) =>
                  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),
            )
          ],
        ),
      ),
    );
  }
}

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

我在这里定义了 cashCounterProvider,当我尝试将值输入 TextFormField 时,我无法输入多个值,此行为

Text('${cashCounterProvider.count + cashCounterProvider.cash}'),

确实有效一次。我尝试在输入中多次输入值时实现一个简单的计算器

除非使用 hooks,否则 Flutter 中的控制器需要在构建方法之外声明。每当您在其中一个 TextFields 中键入内容时,就会重建小部件,这会导致您的控制器被重新分配。

如果使用钩子,以下是没问题的:

class CalculatableTextFormField extends HookWidget {
  @override
  Widget build(BuildContext context) {
    final cashCounterProvider = useProvider(cashProvider);
    final TextEditingController _count = useTextEditingController();
    final TextEditingController _cash = useTextEditingController();
    ...

否则,在构建方法之外声明控制器:

class CalculatableTextFormField extends ConsumerWidget {
  final TextEditingController _count = TextEditingController();
  final TextEditingController _cash = TextEditingController();
  
  @override
  Widget build(BuildContext context, ScopedReader watch) {
    final cashCounterProvider = watch(cashProvider);
    ...

我最喜欢的钩子好处之一是不必自己处理处理逻辑。 Here is an example of handling the lifecycle of a TextEditingController. After reading that, take a look at the implementation 对于 useTextEditingController。这应该有助于理解事情是如何运作的。