错误:在此小部件上方找不到正确的提供程序 <List<Auftrag>>

Posted

技术标签:

【中文标题】错误:在此小部件上方找不到正确的提供程序 <List<Auftrag>>【英文标题】:Error: Could not find the correct Provider <List<Auftrag>> above this Widget 【发布时间】:2020-08-04 20:08:00 【问题描述】:

我正在尝试制作一个按钮标签栏,在第一个 Tap 页面上有一个列表(堆栈)。不知何故有这个错误,我只是不知道为什么......

这是我的主页文件:

class  Home extends StatelessWidget 

  final AuthService _auth = AuthService();
  @override
  Widget build(BuildContext context) 
    return TabContainerIndexedStack();

这是 TabContainerIndexStack():

class TabContainerIndexedStack extends StatefulWidget 
  TabContainerIndexedStack(Key key) : super(key: key);

  @override
  _TabContainerIndexedStackState createState() =>
      _TabContainerIndexedStackState();


class _TabContainerIndexedStackState extends State<TabContainerIndexedStack> 
  int tabIndex = 0;
  List<Widget> listScreens;
  @override
  void initState() 
    super.initState();
    listScreens = [
      Tab1(),
      Tab2(),
      Tab3(),
    ];
  

//  @override
//  bool get wantKeepAlive =>
//      true; //by default it will be null, change it to true.

  @override
  Widget build(BuildContext context) 
    return MaterialApp(
      color: Colors.yellow,
      home: Scaffold(
        body: IndexedStack(index: tabIndex, children: listScreens),
        bottomNavigationBar: BottomNavigationBar(
            currentIndex: tabIndex,
            onTap: (int index) 
              setState(() 
                tabIndex = index;
              );
            ,
            items: [
              BottomNavigationBarItem(
                icon: Icon(Icons.home),
                title: Text('Tab1'),
              ),
              BottomNavigationBarItem(
                icon: Icon(Icons.report_problem),
                title: Text('Tab2'),
              ),
              BottomNavigationBarItem(
                icon: Icon(Icons.settings),
                title: Text('Tab3'),
              ),
            ]),
        backgroundColor: Theme.of(context).primaryColor,
      ),
    );
  

这是我的第一个标签(其他标签有效!!!)

class Tab1 extends StatefulWidget 
  @override
  _Tab1State createState() => _Tab1State();


class _Tab1State extends State<Tab1> with AutomaticKeepAliveClientMixin<Tab1> 
  @override
  void initState() 
    super.initState();
    print('initState Tab1');
  

  @override
  Widget build(BuildContext context) 
    print('build Tab1');
    return Scaffold(
      appBar: AppBar(
        title: Text('Tab1'),
      ),
      body: AuftraegeList()
    );
  

  @override
  bool get wantKeepAlive => true;

我认为问题就在上面的“body: AuftraegeList()...”中..

这里是文件 AuftraegeList():

class AuftraegeList extends StatefulWidget 
  @override
  _AuftraegeListState createState() => _AuftraegeListState();


class _AuftraegeListState extends State<AuftraegeList> 
  @override
  Widget build(BuildContext context) 

    final auftraege = Provider.of<List<Auftrag>>(context);

    return ListView.builder(
        itemCount: auftraege.length,
        itemBuilder: (context, index)
      return AuftragTile(auftrag: auftraege[index]);
    ,
    );
  

我希望这足以解决我的问题。我对 Flutter 很陌生,所以如果你能说出我必须在哪里改变什么,那就太好了。非常感谢!!!

编辑:这是我 home.dart 的代码,这是代码,代表我的主视图中的列表。

class  Home extends StatelessWidget 

  final AuthService _auth = AuthService();
  @override
  Widget build(BuildContext context) 
    return TabContainerIndexedStack();
    /*
    return StreamProvider<List<Auftrag>>.value(
    value: DatabaseService().auftraege,
      child: Scaffold(
        bottomNavigationBar: btmBar(),
     backgroundColor: Colors.blue[50],
      appBar: AppBar(
        title: Text('Home title'),
        backgroundColor: Colors.blue,
        elevation: 0.0,
        actions: <Widget>[
          FlatButton.icon(
            icon: Icon(Icons.person),
            label: Text('logout'),
            onPressed: () async
              await _auth.signOut();
            ,
          )
        ],
      ),
        body: AuftraegeList(),
        ),
    );
    */

  

(这是我注释掉的部分)

谢谢!!

编辑(2)!!!

最新编辑:

所以我的第一个点击类现在看起来像这样(我在最初声明 databaseService 后将 Widget 构建主体 [] 更改为 databaseService.auftraege)。

    class Tab1 extends StatefulWidget 
  @override
  _Tab1State createState() => _Tab1State();



class _Tab1State extends State<Tab1> with AutomaticKeepAliveClientMixin<Tab1> 

  // Where should I put this line? Whereever I put this, it gives me errors (already imported services/database.dart)
  final DatabaseService databaseService = Provider.of<DatabaseService()>(context);

  @override
  void initState() 
    super.initState();
    print('initState Tab1');
  

  @override
  Widget build(BuildContext context) 
    print('build Tab1');
    return Scaffold(
      appBar: AppBar(
        title: Text('Tab1'),
      ),
      body: Provider(
        create: (context) => databaseService.auftraege,
        child: AuftraegeList(),
      )
    );
  


  @override
  bool get wantKeepAlive => true;

也许向您展示我的服务/数据库也很有帮助

class DatabaseService

  final String uid;
  DatabaseService( this.uid );
  // collection reference
   final CollectionReference auftraegeCollection = Firestore.instance.collection('auftraege');

  Future updateUserData(String title, String info, int price, String user) async
    return await auftraegeCollection.document(uid).setData(
      'title' : title,
      'info': info,
      'price': price,
      'user': user,
    );
  


  List<Auftrag> _auftragListFromSnapshot(QuerySnapshot snapshot)
    return snapshot.documents.map((doc)
      return Auftrag(
          title: doc.data['title']?? '',
          info: doc.data['info']?? '',
          price: doc.data['price']?? 0,
          user: doc.data['user']?? '',

      );
    ).toList();
  


  // get auftraege stream
Stream <List<Auftrag>> get auftraege 
    return auftraegeCollection.snapshots()
    .map(_auftragListFromSnapshot);


当留下这样的代码时,它在这一行给我一个错误:

 final DatabaseService databaseService = Provider.of<DatabaseService()>(context);

在我的 tab1.dart 课程中。它在“上下文”和“错误:比较表达式不能是另一个比较表达式的操作数”以及“错误:未定义运算符'

也许你知道该怎么做。我想我只是把这条线放在了错误的地方。

### 编辑 (3) ### (例外)

════════ 小部件库捕获的异常════════════════════════════════ ═════════════════════ 在构建 _BodyBuilder 时抛出了以下断言: 在 _Tab1State.initState() 完成之前调用了dependOnInheritedWidgetOfExactType>() 或dependOnInheritedElement()。

当继承的小部件发生变化时,例如,如果 Theme.of() 的值发生变化,则重新构建其依赖的小部件。如果依赖小部件对继承小部件的引用在构造函数或 initState() 方法中,则重建的依赖小部件将不会反映继承小部件中的更改。

通常对继承的小部件的引用应该出现在小部件的 build() 方法中。或者,可以将基于继承的小部件的初始化放在 didChangeDependencies 方法中,该方法在 initState 之后以及此后依赖关系发生变化时调用。

相关的导致错误的小部件是: 脚手架文件:///Users/xxxxxxxxxxxxxxx/androidStudioProjects/promi_prototype/lib/screens/home/tab_containter_indexedstack.dart:36:13 抛出异常时,这是堆栈:

0 StatefulElement.dependOnInheritedElement。 (包:flutter/src/widgets/framework.dart:4467:9)

1 StatefulElement.dependOnInheritedElement(包:flutter/src/widgets/framework.dart:4510:6)

2 StatefulElement.inheritFromElement (package:flutter/src/widgets/framework.dart:4458:12)

3 Element.inheritFromWidgetOfExactType (package:flutter/src/widgets/framework.dart:3556:14)

4 Provider.of (package:provider/src/provider.dart:259:19)

它说,相关的导致错误的小部件是:tab_containter_indexedstack.dart,我已经在帖子的开头发布了这段代码。模拟器现在只显示蓝色背景,底部有标签栏。其他选项卡上没有文本(以前工作过),并且 tab1 上没有错误警告。甚至没有标题。

你好!! :)

.

.

.

### 编辑(4)###

我的上帝 xD 很抱歉没有工作......感谢您仍然提供帮助!

让我们开始我的错误信息:

在构建 Provider>>(dirty, state: 颤振:_DelegateWidgetState#eb784): flutter:尝试使用带有 Listenable/Stream (Stream>) 子类型的 Provider。 扑: flutter:这可能是一个错误,因为 Provider 不会自动更新依赖项 颤振:当 Stream> 更新时。相反,请考虑将 Provider 更改为更具体的 flutter:处理更新机制的实现,如: 扑: 颤振:-ListenableProvider 颤振: - ChangeNotifierProvider 颤振:-ValueListenableProvider 颤振:-StreamProvider 相关的导致错误的小部件是: 颤振:提供者>> 颤振:file:///Users/xxxxxxxxxxxx/AndroidStudioProjects/promi_prototype/lib/screens/my_tabs/tab1.dart:33:13

所以 tab1.dart 中的 Provider 仍然存在问题。我的猜测是更改 AuftragList() 中的 Provider 的东西,因为我在那里使用它的“旧”方式,如 Provider.of>(context),就像你在 18 小时前的编辑中提到的那样。

这就是我所做的(之前被注释掉了):

class AuftraegeList extends StatefulWidget 
  @override
  _AuftraegeListState createState() => _AuftraegeListState();


class _AuftraegeListState extends State<AuftraegeList> 

  DatabaseService databaseService ;

  @override
  Widget build(BuildContext context) 

    databaseService = Provider.of<DatabaseService>(context);
   // final auftraege = Provider.of<List<Auftrag>>(context);

    return ListView.builder(
       // itemCount: auftraege.length,
       // itemBuilder: (context, index)
          itemCount: databaseService.length, //RED MARK HERE
          itemBuilder: (context, index)
      return AuftragTile(auftrag: databaseService[index]); //RED MARK HERE
    ,
    );
  

我认为现在可以了,但我在“.lenght”和“[index]”下得到了红色标记。编译器说,我应该在 helpers/database.dart 中创建一个 getter,这就是我当时尝试的方法。但没有成功。然后我删除了那里的吸气剂。

你有什么想法吗?即使编译器说问题在 tap1.dart 中,更改 AuftraegeList() 中的 Provider 是否正确?

.

【问题讨论】:

您是否使用提供程序包包装了材料小部件? 【参考方案1】:

编辑 由于您没有立即使用 Home 类中的 Stream 提供程序的值,因此您可以使用 Provider 代替,如下所示;

class  Home extends StatelessWidget 

  final AuthService _auth = AuthService();
  @override
  Widget build(BuildContext context) 
    return Provider(
                  create: (context) => DatabaseServices(), 
                  child: TabContainerIndexedStack()
     );
   ,
 

然后当你需要列表时,你必须调用Service 类的提供者而不是列表

final DatabaseService databaseService = Provider.of&lt;DatabaseService&gt;(context);

然后您可以访问列表的实例,例如

databaseService.auftraege

编辑 1

假设您在 home 类中有提供程序,不需要再次将提供程序包装在 AuftraegeList() 周围。这是你应该做的。

class _Tab1State extends State<Tab1> with AutomaticKeepAliveClientMixin<Tab1> 


  final DatabaseService databaseService; 

  @override
  void initState() 
    databaseService = Provider.of<DatabaseService>(context);
    super.initState();
    print('initState Tab1');
  

  @override
  Widget build(BuildContext context) 
    print('build Tab1');
    return Scaffold(
      appBar: AppBar(
        title: Text('Tab1'),
      ),
      body:
        // The use the list directly in this class where needed like `databaseService.auftraege` 
        child: AuftraegeList(),
      )
    );
  


  @override
  bool get wantKeepAlive => true;

注意

    在有状态小部件中,BuildContextinitState 方法和build 方法中可用。所以你可以在这些方法中使用BuildContext,除非你隐式传递它。 如果您需要AuftragList() 类中的列表,请获取一个实例 使用Provider.of&lt;DatabaseService&gt;(context) 的列表 如果您需要列表在有需求时自动更新,您可以使用StreamSubscription 来收听需求流并添加到列表中。 当调用provider of 时传递数据类型而不是类。那是Provider.of&lt;DatabaseService&gt;(context) 而不是Provider.of&lt;DatabaseService()&gt;(context)

编辑 2

既然您正在为您的列表获取流,请使用 steamBuilder 来构建您的 Ui

class AuftraegeList extends StatefulWidget 
  @override
  _AuftraegeListState createState() => _AuftraegeListState();


class _AuftraegeListState extends State<AuftraegeList> 

  DatabaseService databaseService ;

  @override
  Widget build(BuildContext context) 

    databaseService = Provider.of<DatabaseService>(context);
   // final auftraege = Provider.of<List<Auftrag>>(context);

    return StreamBuilder<List<Auftrag>>( 
        stream: databaseService.auftraege,
        builder: (context, snapshot) 
             if (snapshot.hasData) 
              return  ListView.builder(
                   itemCount: snapshot.data.length, 
                   itemBuilder: (context, index)
                       return AuftragTile(auftrag: snapshot.data[index]);
                   
              );
             else if(snapshot.hasError)
               return Center(child: Text("An error Errored");
             
             return Center(child: CircularProgessIndicator();
      ,

    );
  

希望这可行。

【讨论】:

谢谢 Loic Fonkam!但不知何故,用 > 替换 [] 是行不通的。我在顶部编辑了我的主要问题并添加了代码,它显示了我的列表(没有标签栏)。 好的 Loïc Fonkam,感谢您的努力!我尝试按照您的步骤操作,几乎完成但仍然无法正常工作。我再次编辑了上面的主要帖子,所以你知道我改变了什么。它在“编辑(2)!!!最新编辑:”下的所有内容: 使用参数listen:flase like databaseService = Provider.of&lt;DatabaseService&gt;(context, listen: false); 如果还是报错,则将databaseService的初始化从initState移到build方法 嗯尝试了很多事情,但不知何故仍然无法正常工作。在“'###编辑(4)###”下的主要帖子中的详细说明

以上是关于错误:在此小部件上方找不到正确的提供程序 <List<Auftrag>>的主要内容,如果未能解决你的问题,请参考以下文章

错误:在此 UpdateSupervisor 小部件上方找不到正确的 Provider<NewUser>

ProviderNotFoundException(错误:在此主页小部件上方找不到正确的 Provider<EntryProvider>

错误:在此 Directioner 小部件上方找不到正确的 Provider<User>

我收到错误消息:在此设置小部件上方找不到正确的 Provider<User>(已修复)

找不到正确的提供者

在此 AddSupervisor 小部件上方找不到正确的 Provider<SupervisorProvider>