【问题标题】:Why is ChangeNotifierProvider.value not updating its builder?为什么 ChangeNotifierProvider.value 不更新其构建器?
【发布时间】:2021-01-21 15:02:32
【问题描述】:

我有很多数据对象。每个都有一个ChangeNotifier。所以我想更新尽可能小的区域。必须进行哪些更改才能使此示例正常运行?

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

void main() {
  runApp(MyApp());
}

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

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  MyData _myData;

  @override
  void initState() {
    _myData = MyData(title: 'Really my data');
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Provider Test'),
      ),
      body: Center(
        child: ChangeNotifierProvider<MyData>.value(
          value: _myData,
          builder: (BuildContext _, Widget __) {
            return Column(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: <Widget>[
                Text(_myData.toString()),
                RaisedButton(
                  child: Text('edit'),
                  onPressed: () => _myData.incrementCounter(),
                ),],);},),),);}}

class MyData with ChangeNotifier {
  String title;
  int counter = 0;

  MyData({
    this.title,
  });

  void incrementCounter() {
    counter++;
    print('counter=$counter');
    notifyListeners();
  }

  void setTitle(String newValue) {
    title = newValue;
    notifyListeners();
  }

  String toString() => '$title - $counter';
}

【问题讨论】:

    标签: flutter flutter-provider


    【解决方案1】:

    使用ChangeNotifierProvider&lt;MyData&gt;.value,您将 MyData 提供给它下面的小部件,但您没有在任何地方使用它。要查看 MyData 的变化,请使用 Consumer 小部件。 这是使用消费者的固定代码:

    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: MyHomePage(),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      @override
      _MyHomePageState createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      MyData _myData;
    
      @override
      void initState() {
        _myData = MyData(title: 'Really my data');
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('Provider Test'),
          ),
          body: Center(
            child: ChangeNotifierProvider<MyData>.value(
              value: _myData,
              builder: (BuildContext _, Widget __) {
                return Column(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  children: <Widget>[
                    Consumer<MyData>(
                      builder: (context, mydata, child) {
                        return Text(_myData.toString());
                      },
                    ),
                    RaisedButton(
                      child: Text('edit'),
                      onPressed: () => _myData.incrementCounter(),
                    ),
                  ],
                );
              },
            ),
          ),
        );
      }
    }
    
    class MyData with ChangeNotifier {
      String title;
      int counter = 0;
    
      MyData({
        this.title,
      });
    
      void incrementCounter() {
        counter++;
        print('counter=$counter');
        notifyListeners();
      }
    
      void setTitle(String newValue) {
        title = newValue;
        notifyListeners();
      }
    
      String toString() => '$title - $counter';
    }
    

    【讨论】:

    • 也许你应该使用myData.toString() 而不是_myData.toString()
    • @yellowgray:Hettikas 的回答很好。 @Hettika:是否有任何“提供者”变体将提供已经存在的ChangeNotifier(如MyData)与Consumer 结合在一起?
    • 我尝试将ChangeNotifierProviderConsumer 的组合替换为Provider.value,但收到错误消息:``` 尝试使用具有可监听/流(MyData)子类型的提供程序。这可能是一个错误......考虑使用: -ChangeNotifierProvider 处理更新机制。所以要么消息有误,要么ChangeNotifierProvider有bug
    【解决方案2】:
              void main() {
                runApp(ForProvider());
              }
    
              class ForProvider extends StatefulWidget {
               
                @override
                _ForProviderState createState() => _ForProviderState();
              }
    
              class _ForProviderState extends State<ForProvider> {
                @override
                Widget build(BuildContext context) {
                  return MultiProvider(providers: [
                    ChangeNotifierProvider<MyData>(create: (context) => MyData()),
                  ], child: MyApp());
                }
              }
    
              class MyApp extends StatelessWidget {
                @override
                Widget build(BuildContext context) {
                  return MaterialApp(
                    home: MyHomePage(),
                  );
                }
              }
    
              class MyHomePage extends StatefulWidget {
                @override
                _MyHomePageState createState() => _MyHomePageState();
              }
    
              class _MyHomePageState extends State<MyHomePage> {
                MyData _myData;
    
                @override
                void initState() {
                  _myData = MyData(title: 'Really my data');
                  super.initState();
                }
    
                @override
                Widget build(BuildContext context) {
                  return Scaffold(
                    appBar: AppBar(
                      title: Text('Provider Test'),
                    ),
                    body: Center(
                      child: Consumer<MyData>(
                        builder: (context, myData, child) {
                          return Column(
                            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                            children: <Widget>[
                              Consumer<MyData>(
                                builder: (context, myData, child) {
                                  return Text(myData.toString());
                                },
                              ),
                              RaisedButton(
                                child: Text('edit'),
                                onPressed: () => myData.incrementCounter(),
                              ),
                            ],
                          );
                        },
                      ),
                    ),
                  );
                }
              }
    
              class MyData with ChangeNotifier {
                String title;
                int counter = 0;
    
                MyData({
                  this.title,
                });
    
                void incrementCounter() {
                  counter++;
                  print('counter=$counter');
                  notifyListeners();
                }
    
                void setTitle(String newValue) {
                  title = newValue;
                  notifyListeners();
                }
    
                String toString() => '$title - $counter';
              }
    

    【讨论】:

    • 嗨尼特什。感谢您的回答。但是您的方法会导致“错误:在此 Consumer 小部件...上方找不到正确的 Provider...”。我建议事先测试你的答案,除非你 110% 确定它们有效:-)
    • 嗨 Hajo,我认为您尚未在 MyHomePage 类之上初始化您的提供程序。您需要像这样在 MyHomePage 类上方初始化您的 MyData 提供程序。 "ChangeNotifierProvider(create: (context) => MyData())"
    • 嗨哈乔,我已经编辑了代码,请尝试使用它。
    • 嗨尼特什。谢谢你的支持。您的方法类似于 Hetika 的方法。您在使用它的值之前插入一个“Provider”。我仍在寻找一个像“Provider.value”这样的小部件,它会在像“Provider.of”这样的值发生变化时重建。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-26
    • 2016-11-10
    • 1970-01-01
    • 2010-10-08
    • 1970-01-01
    • 2020-02-19
    • 2023-01-27
    相关资源
    最近更新 更多