Flutter Provider导航到另一个屏幕时失去值

6

我是Flutter和provider package的新手,希望能得到帮助。我的问题是关于main.dart文件的,该文件内容如下:

 void main() => runApp(
      MaterialApp(
        debugShowCheckedModeBanner: false,
        theme: ThemeData.light(),
        home: ChangeNotifierProvider(
          create: (_) => InterestingMomentProvider(),
          child: Home(),
        ),
     ),
  );

这是构建我的Home插件,由于它非常大,我不会全部贴出来。然而,当我点击一个按钮时,它将字符串传递给提供程序类并将其添加到列表中,如下所示:

import 'package:flutter/widgets.dart';

class InterestingMomentProvider extends ChangeNotifier {

  List<String> _moments = [];

  List<String> get moments => _moments;

  void addMoment(String time){
    _moments.add(time);
  }

  int momentsTotal(){
    return _moments.length;
  }

}

在 addMoment 方法中添加一个断点,我可以确认_moments 中包含所有字符串。

然后我按下一个按钮,导航到另一个屏幕,导航代码如下:

Navigator.push(context, MaterialPageRoute(builder: (context) => MomentsRecorded()),);

MomentsRecorded小部件如下:
class MomentsRecorded extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Moments'),
        centerTitle: true,        
      ),
      body: Center(
        child: MomentsList()
        ),
    );
  }
}

第一个错误是:
Could not find the correct Provider<InterestingMomentProvider> above this Consumer<InterestingMomentProvider> Widget

To fix, please:

  * Ensure the Provider<InterestingMomentProvider> is an ancestor to this Consumer<InterestingMomentProvider> Widget
  * Provide types to Provider<InterestingMomentProvider>
  * Provide types to Consumer<InterestingMomentProvider>
  * Provide types to Provider.of<InterestingMomentProvider>()
  * Always use package imports. Ex: `import 'package:my_app/my_code.dart';
  * Ensure the correct `context` is being used.

我随后微调了代码,使得页面的body区块看起来像下面这样,错误就消失了:

 body: Center(
        child: ChangeNotifierProvider(
          create: (_) => InterestingMomentProvider(),
          child: MomentsList())
        ),

然而,在MomentLists小部件内,我试图循环遍历来自提供程序类的时刻列表,但是当调试_moments时为0?

MomentsList小部件:

class MomentsList extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Consumer<InterestingMomentProvider>(
      builder: (context, momentData, child){
        return momentData.momentsTotal() > 0 ? ListView.builder(
          itemCount: momentData.momentsTotal(),
          itemBuilder: (BuildContext context, int index) {
            final moment = momentData.moments[index];
            return ListTile(
                title: Text(moment),
            );
          }
        ) : Center(child: Text('no moments recorded'),);
      }

    );
  }
}

有人可以解释一下这个可能的原因是什么吗?
1个回答

17

这种情况发生是因为你的提供者在MaterialApphome属性中定义,所以当你更改路由时,提供者也会被删除。

解决方案:将提供者移到MaterialApp上面,像这样:

 void main() => runApp(
  ChangeNotifierProvider(
    create: (_) => InterestingMomentProvider(),
    child: MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData.light(),
      home: Home()
    ),
  ),
);

如果您担心这不是正确的方法- 查看文档,他们也在使用同样的方法


我正在学习Flutter的早期阶段,因此我会听取其他经验比我丰富的开发人员的任何文档或建议。以上内容有效,非常感谢,我一定会查看文档并遵循所概述的示例。 - Code Ratchet
谢谢兄弟,我花了很多时间来解决这个问题。最终,我得到了你的答案。 - Shahzad Akram
我之前没有理解到的是路由是MaterialApp的一部分。因此,我认为在material app之后定义一些providers是可以的。然而,这与“将状态保持在使用它的小部件上方”建议相矛盾。因为MaterialApp是最早的小部件之一,或者我有什么地方理解错误吗? - cksrc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接