【问题标题】:Builder widget for ChangeNotifier in FlutterFlutter 中 ChangeNotifier 的构建器小部件
【发布时间】: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

标签: flutter dart flutter-change-notifier


【解决方案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}');
            }
          ),
        ),
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2022-06-22
          • 2017-10-19
          • 2020-06-09
          • 2020-11-11
          • 2022-01-11
          • 2020-12-14
          • 1970-01-01
          • 2021-11-11
          相关资源
          最近更新 更多