Riverpod:在 ConsumerWidget 中覆盖 initState 的另一种方法

Posted

技术标签:

【中文标题】Riverpod:在 ConsumerWidget 中覆盖 initState 的另一种方法【英文标题】:Riverpod : Alternate way of overriding initState inside ConsumerWidget 【发布时间】:2021-01-19 17:46:09 【问题描述】:

因为这里的initState方法不可覆盖,所以在consumerWidget里面初始化东西的解决办法是什么?

【问题讨论】:

【参考方案1】:

更新

Riverpod v1.0.0

您可以使用ConsumerStatefulWidget 和ConsumerState

final helloWorldProvider = Provider((_) => 'Hello world');

class RiverpodExample extends ConsumerStatefulWidget 
  @override
 _RiverpodExampleState createState() => _RiverpodExampleState();


class _RiverpodExampleState extends ConsumerState<Example> 

  @override
  void initState() 
    super.initState();

    final value = ref.read(helloWorldProvider);

  

  @override
  Widget build(BuildContext context) 
    final value = ref.watch(helloWorldProvider);

    return Text(value); // Hello world
  


Riverpod v0.14.0+3

您必须使用 StatefulWidget 并从 build 方法返回 Consumer 作为根小部件。

消费者

Consumer 可用于在 StatefulWidget 或 在提供程序更新时重建尽可能少的小部件。

final helloWorldProvider = Provider((_) => 'Hello world');

class RiverpodExample extends StatefulWidget 
  @override
  _RiverpodExampleState createState() => _RiverpodExampleState();


class _RiverpodExampleState extends State<Example> 

  @override
  void initState() 
    super.initState();

  

  @override
  Widget build(BuildContext context) 
    return Consumer(
      builder: (context, watch, child) 
        final value = watch(helloWorldProvider);
        return Text(value); // Hello world
      ,
    );
  

【讨论】:

是的,这可能是一个解决方案,但它完全忽略了 Riverpod / ConsumerWidget 的强大功能 我不认为现在有任何其他方式@towhid @VinothVino 似乎 ConsumerStateMixin 在 flutter_riverpod 1.0.0 上不再可用【参考方案2】:

我不完全确定如何回答您的问题,因为我没有使用 ConsumerWidget。我认为这个想法是将您的大部分状态保留在提供程序中。

但是,我想建议在 flutter_hooks 旁边使用 hooks_riverpod(相同的 developer)。

这使得保持小部件本地状态变得简单,并且还提供了对提供程序的轻松访问。

例如:

class Example extends HookWidget 
  const Example(Key key) : super(key: key);

  @override
  Widget build(BuildContext context) 
    final test = useProvider(Test.provider());

    final controller = useTextEditingController();
    final loading = useState(false);
    final buttonText = useState('Change me!');

    return Column(
      children: [
        TextField(controller: controller),
        if (!loading) RaisedButton(
          onPressed: () async 
            loading.value = true;
            await Future.delayed(const Duration(seconds: 1));
            buttonText.value = controller.text;
            loading.value = false;
          
          child: Text(buttonText.value),
        ),
        if (loading) const CircularProgressIndicator(),
        // Do something with providers, etc.
      ],
    ),
  );

只是一个简单的示例,但有很多资源(flutter_hooks、hooks_riverpod)可以帮助您。另外,请查看 examples from the developer 了解 Riverpod 挂钩的使用情况。

【讨论】:

在您的回答指导下编写了我的代码后,我可以得出结论,这是使用 hook_riverpod 实现 flutter_hooks 并在小部件启动时设置变量的正确方法(并且它在文档中)。这是因为即使您重建它,初始值也不会覆盖您可以在返回的小部件中设置或更新的内容,所以它与使用 initState 完全一样。【参考方案3】:

我可能会迟到,但随着即将推出的 Riverpod 1.0.0,您将能够使用 https://pub.dev/documentation/flutter_riverpod/1.0.0-dev.2/flutter_riverpod/ConsumerStatefulWidget-class.html 和 https://pub.dev/documentation/flutter_riverpod/1.0.0-dev.2/flutter_riverpod/ConsumerState-class.html,这正是您想要的。

【讨论】:

@wujek,Vinoth 接受的答案对我有用。尝试跟随它,看看即使没有链接,你是否也能正确。我认为他们仍在更新文档。 有趣的是他的链接和我的一样坏,但至少他有内联代码;)

以上是关于Riverpod:在 ConsumerWidget 中覆盖 initState 的另一种方法的主要内容,如果未能解决你的问题,请参考以下文章

在 Flutter 中使用 Riverpod 实现 pull-to-refresh

您应该将状态值放在 Riverpod 的啥位置?

Riverpod - 如何在消费者中包装 PreferredSizeWidget

Riverpod : initState 方法中的访问提供程序

RiverPod - 如何在不在小部件中的 AsyncValue 上等待使用 FutureProvider

Riverpod StateNotifier 不适用于悬停逻辑