【问题标题】:Flutter provider state not updating in consumer widgetFlutter 提供者状态未在消费者小部件中更新
【发布时间】:2019-10-10 06:58:30
【问题描述】:

我正在尝试使用提供程序跨页面设置状态。但它没有改变。

我在 main.dart 中添加了 changeNotifierProvider main.dart

    class MyApp extends StatelessWidget {
      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
        return MultiProvider(
          providers: [
            ChangeNotifierProvider(builder: (context) => GlobalState())
          ],
        child: MaterialApp(
            title: 'Flutter Demo',
            theme: ThemeData(
              primarySwatch: Colors.blue,
            ),
            routes: {
              '/': (context) => HomePage(),
              '/products': (context) => ProductsPage()
            }
          )
        );
      }
    }

我正在尝试设置并获取一个简单的名称字符串

globatState.dart

    class GlobalState extends ChangeNotifier{
      String _name = 'Hello';
      String get getName => _name;
      void setName(String value){
        _name = value;
        notifyListeners();
      }
    }

在主页中,我正在设置状态,可以使用导航器 pushNamed 路由移动到产品页面。

主页.dart

    class HomePage extends StatelessWidget {
      @override
      Widget build(BuildContext context){
        GlobalState gs = GlobalState();
        return Scaffold(
          appBar: AppBar(title: Text('Home'),),
          body: Container(
            child: Column(children: <Widget>[
              RaisedButton(onPressed: ((){
                gs.setName('World');
                }),
                child: Text('Set data'),
              ),
              RaisedButton(
                onPressed: () => Navigator.pushNamed(context, '/products'),
                child: Text('Products'),
              ),
            ],)

          ),
        );
      }
    }

在产品页面中,我使用消费者来获取状态 productsPage.dart

    class ProductsPage extends StatelessWidget{
      @override
      Widget build(BuildContext context){
        return Scaffold(appBar: AppBar(title: Text('Products'),
        ),
        body: Container(child:Column(children: <Widget>[
          Text('This is the productPage'),
          Container(
            child:Consumer<GlobalState>(
              builder: (context, gs, child){
                return Text('this is the data: ${gs.getName}');
              },
            )
          )
        ],))
        );
      }
    }

但在产品页面中,我只获得状态的初始值,而不是更改后的状态。是我遗漏了什么还是我导航错误?

【问题讨论】:

  • 首页第4行,改用Provider.of
  • 使用 Provider.of 为我工作。

标签: flutter


【解决方案1】:
GlobalState gs = GlobalState();

将为您的 GlobalState 类创建一个新实例。未注册为提供商。

相反,像这样使用提供者提供的实例

GlobalState gs = Provider.of<GlobalState>(context, listen:false);
gs.setName('world');

【讨论】:

  • 感谢代码 Anand - 如果有人尝试一下,您可能会遇到另一个错误,因为 ChangeNotifierProvider(builder: (context) 已被弃用,现在由 ChangeNotifierProvider(create: (context) - 详细信息在这里stackoverflow.com/questions/59100723/…
【解决方案2】:

尝试使用 pub.dev 上的 equatable 包,链接如下 ->

https://pub.dev/packages/equatable

您可以从 Equatable 扩展一个类,然后在该类内部,您可以使用该类的所有属性/成员变量覆盖 getter props。

发生这种情况是因为当由于 Flutter 使用的性能优化技术从数据源(REST API)更新数据时,它不会比较类实例中的每个属性/成员变量,它指的是对象在内存中的位置只要。使用 equatable,您基本上可以为内存中类的每个对象覆盖 == 运算符和 hashCode,它会将 props getter 变量中每个已定义属性的旧值与新值进行比较,如果任何属性不匹配,那么它将覆盖它,然后您的提供者/消费者将更新 UI,它会反映更新后的状态。

【讨论】:

    猜你喜欢
    • 2020-02-06
    • 1970-01-01
    • 2020-10-03
    • 2021-03-17
    • 1970-01-01
    • 2022-08-08
    • 2020-08-09
    • 2021-01-26
    • 1970-01-01
    相关资源
    最近更新 更多