Flutter 中 ChangeNotifier 的构建器小部件

Posted

技术标签:

【中文标题】Flutter 中 ChangeNotifier 的构建器小部件【英文标题】:Builder widget for ChangeNotifier in Flutter 【发布时间】:2021-07-04 23:35:34 【问题描述】:

背景

ValueNotifier 有一个 ValueListenableBuilder 小部件。 Stream 有一个 StreamBuilder 小部件。 Future 有一个 FutureBuilder 小部件。

问题

ChangeNotifier 的生成器是什么?

我尝试了什么

我尝试将ValueListenableBuilderChangeNotifier 一起使用,但ChangeNotifier 没有实现ValueListenable

我知道我可以使用Provider 包中的ChangeNotifierProvider,但我想知道是否有不需要第三方包的解决方案。

【问题讨论】:

AnimatedBuilder(或者AnimatedWidget,如果你想要一些扩展AnimatedWidget的自定义类) @pskink,很有趣!我不会从名字中猜到的。 有时,我感觉就像走过你走过的那一步。每当我尝试在您的“极简主义”架构上构建时,我都会看到您的解决方案突然出现。我的页面的 ViewModel/Controller/Manager 类是 ChangeNotifier,其中包含多个简单/复杂的 ValueNotifiers。 UI 通过整个 ViewModel notifyListeners() 或其微调属性 ValueNotifiers 得到相应的通知。我使用 ChangeNotifier 作为 ViewModel,因为 ValueNotifier 子类需要相等性检查 == 来通知。这意味着覆盖所说的==+hashCode 或使用Equatable 由于上述原因,我一直在寻找ChangeNotifier builder。这个问题/答案非常适合这种特殊情况。 @om-ha,我喜欢ChangeNotifier,因为它简单易用。不过,我从来不需要在我的值通知程序中覆盖 ==hashCode 【参考方案1】:

这是一个补充答案,演示了使用 AnimatedBuilder 在从 ChangeNotifier 更改时重建 UI。

这只是标准的计数器应用程序。

counter_model.dart

import 'package:flutter/foundation.dart';

class CounterModel extends ChangeNotifier 
  int _counter = 0;

  int get count => _counter;

  void increment() 
    _counter++;
    notifyListeners();
  

main.dart

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

void main() 
  runApp(MyApp());


class MyApp extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return MaterialApp(
      home: MyHomePage(),
    );
  


class MyHomePage extends StatefulWidget 
  MyHomePage(Key key) : super(key: key);
  @override
  _MyHomePageState createState() => _MyHomePageState();


class _MyHomePageState extends State<MyHomePage> 
  final _counterModel = CounterModel();
  @override
  Widget build(BuildContext context) 
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            AnimatedBuilder(
              animation: _counterModel,
              builder: (context, child) 
                return Text(
                  '$_counterModel.count',
                  style: Theme.of(context).textTheme.headline4,
                );
              
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _counterModel.increment,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), 
    );
  

【讨论】:

【参考方案2】:

ChangeNotifier 是 Listenable Widget 的直接实现,对于 Listenable,您可以使用 AnimatedBuilder,它会从 Listenable 触发重建,而无需传回特定值 此外,您的类可以从 ChangeNotifier 扩展并为其添加新功能,您可以基于这些新功能创建自定义 Builder 小部件

【讨论】:

【参考方案3】:

您可以使用消费者来更改和构建您的 UI! 试试这些 - https://flutter.dev/docs/development/data-and-backend/state-mgmt/simple

【讨论】:

Consumer 小部件是提供程序包的一部分,我一直在寻找非第三方解决方案。但是,阅读您的链接很有帮助,因为自从我上次阅读以来它已经更新。【参考方案4】:

您可以自己编写一个简单的小部件。 使用setState 作为ChangeNotifier 的侦听器。

class ChangeNotifierBuilder<T extends ChangeNotifier> extends StatefulWidget 
  const ChangeNotifierBuilder(
    Key? key,
    required this.value,
    required this.builder,
  ) : super(key: key);

  final T value;

  final Widget Function(BuildContext context, T value) builder;

  @override
  _ChangeNotifierBuilderState<T> createState() =>
      _ChangeNotifierBuilderState<T>();


class _ChangeNotifierBuilderState<T extends ChangeNotifier>
    extends State<ChangeNotifierBuilder<T>> 
  @override
  void initState() 
    widget.value.addListener(_listener);
    super.initState();
  

  @override
  void didUpdateWidget(covariant ChangeNotifierBuilder<T> oldWidget) 
    if (widget.value != oldWidget.value) 
      _miggrate(widget.value, oldWidget.value, _listener);
    
    super.didUpdateWidget(oldWidget);
  

  @override
  void dispose() 
    widget.value.removeListener(_listener);
    super.dispose();
  

  void _miggrate(Listenable a, Listenable b, void Function() listener) 
    a.removeListener(listener);
    b.addListener(listener);
  

  void _listener() 
    setState(() );
  

  @override
  Widget build(BuildContext context) 
    return widget.builder(context, widget.value);
  

【讨论】:

【参考方案5】:

ChangeNotifierProviderChangeNotifierProvider.value 和其他提供程序的构建器是 Consumer

ChangeNotifierProvider(
  create: (context) => CounterModel(),
  child: Consumer<CounterModel>(
    builder: (context, model, child) 
      return Text('$model.count');
    
  ),
),

【讨论】:

以上是关于Flutter 中 ChangeNotifier 的构建器小部件的主要内容,如果未能解决你的问题,请参考以下文章

Flutter Listen 的 ChangeNotifier 类,它是 ChangeNotifier 的一个属性

如何在 Flutter 中使用 Provider 显示来自 ChangeNotifier 的错误

Flutter 数据监听器ChangeNotifier

如何关闭 ChangeNotifier Provider Flutter 中的函数

Flutter Provider实现原理

与flutter中更改通知提供程序相关的问题