首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Flutter使用了一个‘`BuildContext`’,它是提供程序的祖先

Flutter使用了一个‘`BuildContext`’,它是提供程序的祖先
EN

Stack Overflow用户
提问于 2020-08-08 13:00:24
回答 1查看 4.1K关注 0票数 2

我正在开发一个颤振应用程序(我仍然是个新手),我被以下错误困住了:

代码语言:javascript
运行
复制
Error: Could not find the correct Provider<List<Category>> above this Exercises Widget

This likely happens because you used a `BuildContext` that does not include the provider
of your choice. There are a few common scenarios:

- The provider you are trying to read is in a different route.

  Providers are "scoped". So if you insert of provider inside a route, then
  other routes will not be able to access that provider.

- You used a `BuildContext` that is an ancestor of the provider you are trying to read.

  Make sure that Exercises is under your MultiProvider/Provider<List<Category>>.
  This usually happen when you are creating a provider and trying to read it immediately.

  For example, instead of:

Widget构建(BuildContext上下文){

返回提供者(

创建:(_) =>示例(),

//将引发一个ProviderNotFoundError,因为context是关联的

//指向作为Provider<Example>父部件的小部件

儿童:文本(context.watch()),

),

}

代码语言:javascript
运行
复制
consider using `builder` like so:

Widget构建(BuildContext上下文){

返回提供者(

创建:(_) =>示例(),

//我们使用builder获得可以访问提供程序的新BuildContext

建设者:(上下文){

//不再投球

返回文本(context.watch()),

}

)、

代码语言:javascript
运行
复制

我一直在网上查找,这显然与我无法在exercises_add.dart中调用exercises_add.dart(Context)时获得正确的“上下文”有关,我真的不明白为什么。因为正如您在我的exercises.dart中看到的,我有'body: ExerciseList()',其中我能够从StreamProvider中获取类别,但是当我试图通过单击'floatingActionButton‘访问它,然后试图打开我的ExerciseAdd()页面时,它会抛出这个错误。

我非常希望有一个解决方案(+解释)来解决如何修复我的代码,以及为什么它不能工作。

exercises.dart

代码语言:javascript
运行
复制
  Widget build(BuildContext context) {
    return _isLoading
        ? Loading()
        : MultiProvider(
            providers: [
              StreamProvider<List<Exercise>>(
                create: (context) => DatabaseService().exercises,
              ),
              StreamProvider<List<Category>>(
                create: (context) => DatabaseService().categories,
              ),
              ChangeNotifierProvider<ExerciseFilter>(
                create: (context) => ExerciseFilter(isActive: true),
              )
            ],
            child: Scaffold(
              appBar: AppBar(
                title: Text('Exercises'),
                elevation: 0.0,
                actions: _buildActions(),
              ),
              body: ExerciseList(),
              floatingActionButton: FloatingActionButton(
                backgroundColor: Colors.black,
                child: Icon(Icons.add, color: Colors.white),
                onPressed: () {
                  Navigator.push(
                     context,
                     MaterialPageRoute(
                       builder: (context) => ExercisesAdd(),
                     ),
                   );
                },
              ),
            ),
          );
  }
 }

exercises_add.dart

代码语言:javascript
运行
复制
 @override
  Widget build(BuildContext context) {
    final cats = Provider.of<List<Category>>(context);
    print(cats.length);

    return Scaffold(
      appBar: AppBar(
        title: Text('Add Exercise'),
        elevation: 0.0,
      ),
      body: SingleChildScrollView(
        child: Container(
          padding: EdgeInsets.symmetric(vertical: 20.0, horizontal: 50.0),
          child: Form(
            key: _formKey,
            child: Column(
              children: <Widget>[
                SizedBox(height: 20.0),
                TextFormField(
                  decoration:
                      textInputDecoration.copyWith(hintText: 'Exercise Name'),
                  validator: (value) {
                    if (value.isEmpty) {
                      return 'Exercise name is required';
                    }

                    return null;
                  },
                  onChanged: (value) {
                    setState(() {
                      exerciseName = value;
                    });
                  },
                ),
                SizedBox(height: 20.0),
                Theme(
                  data: Theme.of(context).copyWith(canvasColor: Colors.white),
                  child: DropdownButtonFormField<String>(
                    decoration: dropdownDecoration,
                    value: exerciseCategory,
                    onChanged: (value) {
                      setState(() {
                        exerciseCategory = value;
                      });
                    },
                    items: categories.map<DropdownMenuItem<String>>((value) {
                      return DropdownMenuItem<String>(
                        value: value.name,
                        child: Text(value.name),
                      );
                    }).toList(),
                  ),
                ),
                SizedBox(height: 20.0),
                RaisedButton(
                  elevation: 0,
                  color: Colors.black,
                  child: Text(
                    'Add Exercise',
                    style: TextStyle(color: Colors.white),
                  ),
                  onPressed: () async {
                    if (_formKey.currentState.validate()) {
                      bool failed = false;
                      String uid = await _auth.getCurrentUser();

                      if (uid != null) {
                        dynamic result = DatabaseService(uid: uid)
                            .addExercise(exerciseName, exerciseCategory);
                        if (result != null) {
                          Navigator.pop(context);
                        } else {
                          failed = true;
                        }
                      } else {
                        failed = true;
                      }

                      if (failed) {
                        setState(() {
                          error = 'Failed to add exercise. Please try again';
                        });
                      }
                    }
                  },
                ),
                SizedBox(height: 12.0),
                Text(
                  error,
                  style: TextStyle(color: Colors.red, fontSize: 14.0),
                ),
              ],
            ),
          ),
        ),
      ),
    );

DatabaseService().exercises

代码语言:javascript
运行
复制
List<Category> _categoryListFromSnapshot(QuerySnapshot snapshot) {
    return snapshot.documents.map((doc) {
      return Category(name: doc.data['category'] ?? '');
    }).toList();
  }

  Stream<List<Category>> get categories {
    return categoryCollection
        .orderBy('category')
        .snapshots()
        .map(_categoryListFromSnapshot);
  }

注: StreamProvider和MultiProvider等。都是“provider”包的一部分(我使用的是最新版本)

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-08-08 13:23:43

您收到的错误描述了当前所处的场景。

您正在尝试读取的

  • The提供程序处于不同的路径。

提供者被“限定范围”。因此,如果在路由中插入提供程序,则其他路由将无法访问该provider.。

您正在导航到不同的路由,并试图访问提供者,但它已不在小部件树中。

您只需将MultiProvider移动到小部件树中所使用的任何导航器之上。您可能会使用MaterialApp来完成这个任务,所以移动MultiProvider并使MaterialApp成为child

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63315716

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档