【问题标题】:Provider: create new model object per each sequence of pages提供者:为每个页面序列创建新的模型对象
【发布时间】:2020-04-20 21:44:21
【问题描述】:

我是Provider 的新手。我正在尝试跨多个页面使用提供者模型。

我有 2 个页面序列。在第一个序列中,只有一个页面IncrementerPage,它只会增加计数。在第二个序列中,有一个OptionsPage,它将显示计数值,并有 2 个选项按钮(Increment & Decrement)。通过单击这些按钮将导航到相应的页面 IncrementerPageDecrementerPage 以增加和减少计数。

注意:sequence1sequence2中,计数应始终从零开始。

这就是我所做的。

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: HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Home Page"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            ChangeNotifierProvider<CounterModel>(
              create: (context) => CounterModel(),
              child: RaisedButton(
                child: Text("Sequence1"),
                onPressed: () {
                  Navigator.push(
                    context,
                    MaterialPageRoute(
                      builder: (context) => IncrementerPage(),
                    ),
                  );
                },
              ),
            ),
            ChangeNotifierProvider<CounterModel>(
              create: (context) => CounterModel(),
              child: RaisedButton(
                child: Text("Sequence2"),
                onPressed: () {
                  Navigator.push(
                    context,
                    MaterialPageRoute(
                      builder: (context) => OptionsPage(),
                    ),
                  );
                },
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class OptionsPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Consumer<CounterModel>(
          builder: (context, model, child) {
            return Text("Count: ${model.count}");
          },
        ),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            RaisedButton(
              child: Text("Increment"),
              onPressed: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(
                    builder: (context) => IncrementerPage(),
                  ),
                );
              },
            ),
            RaisedButton(
              child: Text("Decrement"),
              onPressed: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(
                    builder: (context) => DecrementerPage(),
                  ),
                );
              },
            ),
          ],
        ),
      ),
    );
  }
}

class IncrementerPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Incrementor"),
      ),
      body: Center(
        child: Consumer<CounterModel>(
          builder: (context, model, child) {
            return Text(
              '${model.count}',
              style: const TextStyle(
                fontSize: 32,
                fontWeight: FontWeight.bold,
                color: Colors.black54,
              ),
            );
          },
        ),
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed: () {
          Provider.of<CounterModel>(context, listen: false).increment();
        },
      ),
    );
  }
}

class DecrementerPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Decrementer"),
      ),
      body: Center(
        child: Consumer<CounterModel>(
          builder: (context, model, child) {
            return Text(
              '${model.count}',
              style: const TextStyle(
                fontSize: 32,
                fontWeight: FontWeight.bold,
                color: Colors.black54,
              ),
            );
          },
        ),
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.remove),
        onPressed: () {
          Provider.of<CounterModel>(context, listen: false).decrement();
        },
      ),
    );
  }
}

class CounterModel extends ChangeNotifier {
  int _count = 0;

  int get count => _count;

  void increment() {
    _count++;
    notifyListeners();
  }

  void decrement() {
    _count--;
    notifyListeners();
  }
}

但我收到此错误:

Could not find the correct Provider&lt;CounterModel&gt; above this Consumer&lt;CounterModel&gt; Widget

通过将ChangeNotifierProvider&lt;CounterModel&gt; 移到MaterialApp 之外修复了错误。但是两个页面序列似乎都使用相同的计数器变量(或全局模型)。那么如何为每个页面序列传递不同的模型对象呢?还是有更好的方法来做到这一点?

【问题讨论】:

    标签: flutter provider flutter-provider


    【解决方案1】:

    可能是以下代码导致了异常:

    floatingActionButton: FloatingActionButton(
        child: Icon(Icons.remove),
        onPressed: () {
            Provider.of<CounterModel>(context, listen: false).decrement();
        },
    ),
    

    如您所见,CounterModelChangeNotifierProvider 仅用于序列 1 和 2 的小部件 RaisedButton()

    body 参数下。而floatingActionButtonbody 的同事参数。

    意味着Provider.of&lt;CounterModel&gt; 无法从其父小部件中找到提供程序。

    您可以做的是,将ChangeNotifierProvider 代码移动到覆盖HomePage 并删除应用程序中CounterModel 的所有其他ChangeNotifierProvider 代码。

    【讨论】:

    • 谢谢。但即使我们将ChangeNotifierProvider移到Scaffold上方,也会出现同样的问题。因为Provider.of&lt;CounterModel&gt;(context)不会看之前的路由。
    • 更新了答案,感谢指出。但是根据我的经验,如果通知程序提供程序直接位于脚手架上方,那应该不是问题。所有消费者和Provider.of getter 都将能够获取提供者,因为最顶层的仍然在父窗口小部件的脚手架内。
    • ChangeNotifierProvider 移动到Homepage 上方将不起作用。正如我在问题中提到的,它应该在MaterialApp 之外。问题是如果我这样做,计数器模型将像全局一样。
    • 如果您想为每个序列使用两个不同的模型,则必须分别在每个序列小部件上包装更改通知器。但是浮动操作按钮将无法随意使用。
    猜你喜欢
    • 2011-07-14
    • 1970-01-01
    • 2010-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-30
    • 2020-09-13
    • 1970-01-01
    相关资源
    最近更新 更多