【问题标题】:Flutter : Could not find the correct Provider<EntryProvider> above this Page WidgetFlutter:在此页面小部件上方找不到正确的 Provider<EntryProvider>
【发布时间】:2021-02-03 15:50:07
【问题描述】:

尝试运行时出错,但没有我可以修复的具体问题 试图给出错误给出的例子,但没有运气。该错误甚至说从 stackoverflow 寻求帮助,所以我在这里尝试从谷歌寻求帮助,但没有运气。

错误图片

为什么我的 Provider 在这种情况下会中断?

在我的页面内

  @override
  Widget build(BuildContext context) {
Widget build(BuildContext context) {
    ChangeNotifierProvider<EntryProvider>
      (
      create: (_)=>EntryProvider(),
      child:(MaterialWidget()),
    );
    final entryProvider = Provider.of<EntryProvider>(context);
    return Scaffold(
      appBar: AppBar(
        title: Text('My Journal'),
      ),
      body: StreamBuilder<List<Entry>>(
          stream: entryProvider.entries,
          builder: (context, snapshot) {
            return ListView.builder(
                itemCount: snapshot.data.length,
                itemBuilder: (context, index) {
                  return ListTile(
                    trailing:
                    Icon(Icons.edit, color: Theme.of(context).accentColor),
                    title: Text(
                      formatDate(DateTime.parse(snapshot.data[index].date),
                          [MM, ' ', d, ', ', yyyy]),
                    ),
                    onTap: () {
                      Navigator.of(context).push(MaterialPageRoute(
                          builder: (context) =>
                              EntryScreen(entry: snapshot.data[index])));
                    },
                  );
                });
          }),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed: () {
          Navigator.of(context)
              .push(MaterialPageRoute(builder: (context) => EntryScreen()));
        },
      ),
    );
  }
}

在我的提供者内部

  final firestoreService = FirestoreService();
  DateTime _date;
  String _entry;
  String _entryId;
  var uuid = Uuid();

  //Getters
  DateTime get date => _date;
  String get entry => _entry;
  Stream<List<Entry>> get entries => firestoreService.getEntries();

  //Setters
  set changeDate(DateTime date){
    _date = date;
    notifyListeners();
  }

  set changeEntry(String entry){
    _entry = entry;
    notifyListeners();
  }

  //Functions
  loadAll(Entry entry){
    if (entry != null){
      _date = DateTime.parse(entry.date);
      _entry =entry.entry;
      _entryId = entry.entryId;
    } else {
      _date = DateTime.now();
      _entry = null;
      _entryId = null;
    }
  }

  saveEntry(){
    if (_entryId == null){
      //Add
      var newEntry = Entry(date: _date.toIso8601String(), entry: _entry, entryId: uuid.v1());
      print(newEntry.entry);
      firestoreService.setEntry(newEntry);
    } else {
      //Edit
      var updatedEntry = Entry(date: _date.toIso8601String(), entry: _entry, entryId: _entryId);
      firestoreService.setEntry(updatedEntry);
    }
  }

  removeEntry(String entryId){
    firestoreService.removeEntry(entryId);
  }

}```

class EntryScreen extends StatefulWidget {
  final Entry entry;

  EntryScreen({this.entry});

  @override
  _EntryScreenState createState() => _EntryScreenState();
}

class _EntryScreenState extends State<EntryScreen> {

  final entryController = TextEditingController();

  @override
  void dispose() {
    entryController.dispose();
    super.dispose();
  }

  @override
  void initState() {
    final entryProvider = Provider.of<EntryProvider>(context,listen: false);
    if (widget.entry != null){
      //Edit
      entryController.text = widget.entry.entry;

      entryProvider.loadAll(widget.entry);
    } else {
      //Add
      entryProvider.loadAll(null);
    }
    super.initState();
  }


  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<EntryProvider>
    (
        create: (_)=>EntryProvider(),
        child: Scaffold(
          body: Consumer<EntryProvider>(
            builder: (context, entryProvider, child){
            return Scaffold(
              appBar: AppBar(title: Text(formatDate(entryProvider.date, [MM, ' ', d, ', ', yyyy])),
              actions: [

                IconButton(
                  icon: Icon(Icons.calendar_today),
                  onPressed: (){
                    _pickDate(context,entryProvider).then((value) {
                      if (value != null){
                        entryProvider.changeDate = value;
                      }
                    });
                  },
                )
                ],),
              body: Padding(
                padding: const EdgeInsets.all(8.0),
                child: ListView(
                  children: [
                    TextField(
                      decoration: InputDecoration(
                        labelText: 'Daily Entry', border: InputBorder.none,
                      ),
                      maxLines: 12,
                      minLines: 10,
                      onChanged: (String value) => entryProvider.changeEntry = value,
                      controller: entryController,
                    ),
                    RaisedButton(
                      color: Theme.of(context).accentColor,
                      child: Text('Save',style: TextStyle(color: Colors.white)),
                      onPressed: () {
                        entryProvider.saveEntry();
                        Navigator.of(context).pop();
                      },
                    ),
                    (widget.entry != null) ? RaisedButton(
                      color: Colors.red,
                      child: Text('Delete',style: TextStyle(color: Colors.white)),
                      onPressed: () {
                        entryProvider.removeEntry(widget.entry.entryId);
                        Navigator.of(context).pop();
                      },
                    ): Container(),
                  ],
                ),
              ),
            );
            }
          )
        )
    );
  }

   Future<DateTime> _pickDate(BuildContext context, EntryProvider entryProvider) async {
    final DateTime picked = await showDatePicker(
      context: context, initialDate: entryProvider.date, firstDate: DateTime(2019),
       lastDate: DateTime(2050));
    if (picked != null) return picked;
  }
}```

在我的另一个文件中做了同样的事情,但那个文件仍然出现同样的错误

【问题讨论】:

    标签: firebase flutter dart


    【解决方案1】:

    您需要在页面的父级中创建 ChangeNotifierProvider 小部件,以便它可以在获取提供程序后。因为现在它会尝试寻找您的提供者,但在树中找不到它。

    ChangeNotifierProvider<EntryProvider>(
     create: (_) => EntryProvider(),
     child: YourPageWidget(),
    )
    

    你的例子:

    return ChangeNotifierProvider<EntryProvider>
          (
          create: (_)=>EntryProvider(),
          child: Scaffold(
            body: Consumer<EntryProvider>(
              builder: (context, entryProvider, child){
                return StreamBuilder<List<Entry>>(
                    stream: entryProvider.entries,
                    builder: (context, snapshot) {
                      return ListView.builder(
                          itemCount: snapshot.data.length,
                          itemBuilder: (context, index) {
                            return ListTile(
                              trailing:
                              Icon(Icons.edit, color: Theme.of(context).accentColor),
                              title: Text(
                                formatDate(DateTime.parse(snapshot.data[index].date),
                                    [MM, ' ', d, ', ', yyyy]),
                              ),
                              onTap: () {
                                Navigator.of(context).push(MaterialPageRoute(
                                    builder: (context) =>
                                        EntryScreen(entry: snapshot.data[index])));
                              },
                            );
                          });
                    });
              },
            ),
          )
        );
    

    【讨论】:

    • 在这种情况下会是什么样子?
    • 我的意思是您需要在创建小部件之前创建 ChangeNotifierProvider(我的意思是在代码中而不是在目录中)。因此,您需要在调用页面小部件的小部件中创建它,因为对于提供者,您首先必须创建提供者,然后才能使用 Consumer 或 Provider.of(context) 访问值。
    • 试过 ChangeNotifierProvider ( create: (_)=>EntryProvider(), child:(ExplorePage()), );仍然得到相同的目录评论很愚蠢,我一想到就被删除了,被这个卡住了几个小时,所以大脑有点死了
    • 您能否用新的更改更新您的代码,看看我是否能看到错误。
    • 漂亮,大错误消失了但是现在我尝试调用 Provider.of。这可能是一个错误,因此不受支持。如果您想公开一个可以是任何变量的变量,请考虑将dynamic 改为Object。 'package:provider/src/provider.dart': 断言失败: line 304 pos 7: 'T != dynamic'
    【解决方案2】:

    更简单的选择,而不是尝试包装小部件,而是包装主要部件,因此一切都可以正常工作

       @override
       Widget build(BuildContext context) {
       return MultiProvider(
        providers: [
          StreamProvider<NUser>.value(
            value: AuthService().user,
          ),
          ChangeNotifierProvider<EntryProvider>(
            create: (context) => EntryProvider(),
          )
        ],
        child: MaterialApp(
          home:Wrapper(),
        ),
            );```
    

    【讨论】:

      猜你喜欢
      • 2021-11-24
      • 2021-07-16
      • 1970-01-01
      • 1970-01-01
      • 2020-09-25
      • 2021-09-28
      • 1970-01-01
      • 2021-10-22
      • 2021-08-24
      相关资源
      最近更新 更多