【问题标题】:Why "StateNotifierProvider + Consumer" is not rebuilding the widget?为什么“StateNotifierProvider + Consumer”不重建小部件?
【发布时间】:2021-08-05 07:29:59
【问题描述】:

这是使用riverpod_flutter包的flutter应用的de main.dart文件。

从 3 开始,每次单击时计数器的值都会增加 2,但屏幕不会刷新(在控制台打印时显示 3:5、7、9 等...)。

这是“StateNotifierProvider + Consumer”的代码,但是当我使用 ConsumerWidget 而不是 Consumer 时,我得到了相同的结果。

有什么建议吗?

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

final counterProvider = StateNotifierProvider<Counter, int>((ref) => Counter());

class Counter extends StateNotifier<int> {
  Counter() : super(3);

  String toString() => state.toString();

  void increment() => state++;
  void decrement() => state--;
}

void main() {
  runApp(ProviderScope(
    child: MyApp(),
  ));
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'RiverPod Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Home Page'),
    );
  }
}

class MyHomePage extends StatelessWidget {
  final String title;

  const MyHomePage({Key? key, required this.title}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('RiverPod example'),
      ),
      body: Container(
        child: Center(
          child: Consumer(builder: (context, watch, child) {
            Counter data = context.read(counterProvider.notifier);
            Counter data2 = watch(counterProvider.notifier);

            return Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Text(data.toString()),
                Text(data2.toString()),
                SizedBox(
                  height: 10,
                ),
                FloatingActionButton(
                  onPressed: () {
                    context.read(counterProvider.notifier).increment();
                    data2.increment();
                    print(data.toString());
                  },
                  child: const Icon(Icons.add),
                )
              ],
            );
          }),
        ),
      ),
    );
  }
}

谢谢。

【问题讨论】:

    标签: flutter riverpod


    【解决方案1】:

    使用watch(counterProvider.notifier),您实际上并不是在观察状态,而是在观察通知程序本身(这就是您可以调用增量的原因)。您不应该使用watch 来获取通知程序,而只能使用context.read(就像您使用data 属性所做的那样)。

    要在状态更改时重建,您必须查看实际状态:watch(counterProvider);。这将返回整数状态,然后您可以使用它来显示当前值。

    您也不应该直接从通知程序(您的toString)方法获取状态。 StateNotifier 应该用于管理状态,但实际状态本身应该用于呈现小部件。

    【讨论】:

    • 嗯...对不起,我已经测试了我认为您试图告诉我的内容,但它不起作用。你能给我提供一些类似“将这行代码更改为另一行”之类的内容吗?
    【解决方案2】:

    更改 1:

    而不是这个:

        Counter data = context.read(counterProvider.notifier);
        Counter data2 = watch(counterProvider.notifier);
    

    使用这个:

        final int data = context.read(counterProvider);
        final int data2 = watch(counterProvider);
    

    更改 2:

    而不是这个:

        context.read(counterProvider.notifier).increment();
        data2.increment();
    

    使用这个:

         context.read(counterProvider.notifier).increment();
         watch(counterProvider.notifier).increment();
                    
    

    更改 3(可选,无需使其生效):

    评论这一行:

         //String toString() => state.toString();
    

    更改 4(可选,无需使其生效):

    而不是这个:

         final counterProvider = StateNotifierProvider<Counter, int>((ref) => Counter());
    

    使用这个:

         final counterProvider = StateNotifierProvider((ref) => Counter());
    

    但如果你这样做了,你也需要改变这个:

         final int data = context.read(counterProvider);
         final int data2 = watch(counterProvider);
    

    为此:

         final int data = (context.read(counterProvider) as int);
         final int data2 = (watch(counterProvider) as int);
    

    或者这个:

         final data = context.read(counterProvider);
         final data2 = watch(counterProvider);
    

    这是最终代码(一个版本):

    import 'package:flutter/material.dart';
    import 'package:flutter_riverpod/flutter_riverpod.dart';
    
    final counterProvider = StateNotifierProvider((ref) => Counter());
    
    class Counter extends StateNotifier<int> {
      Counter() : super(3);
    
      //String toString() => state.toString();
    
      void increment() => state++;
      void decrement() => state--;
    }
    
    void main() {
      runApp(ProviderScope(
        child: MyApp(),
      ));
    }
    
    class MyApp extends StatelessWidget {
      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'RiverPod Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: MyHomePage(title: 'Home Page'),
        );
      }
    }
    
    class MyHomePage extends StatelessWidget {
      final String title;
    
      const MyHomePage({Key? key, required this.title}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('RiverPod example'),
          ),
          body: Container(
            child: Center(
              child: Consumer(builder: (context, watch, child) {
                //Counter data = context.read(counterProvider.notifier);
                //Counter data2 = watch(counterProvider.notifier);
                final int data = (context.read(counterProvider) as int);
                final int data2 = (watch(counterProvider) as int);
    
                return Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Text(data.toString()),
                    Text(data2.toString()),
                    SizedBox(
                      height: 10,
                    ),
                    FloatingActionButton(
                      onPressed: () {
                        context.read(counterProvider.notifier).increment();
                        watch(counterProvider.notifier).increment();
                        print(data.toString());
                      },
                      child: const Icon(Icons.add),
                    )
                  ],
                );
              }),
            ),
          ),
        );
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2020-12-22
      • 2021-03-03
      • 2019-07-12
      • 2018-08-29
      • 1970-01-01
      • 1970-01-01
      • 2019-11-02
      • 2021-12-31
      • 2021-09-19
      相关资源
      最近更新 更多