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

时间:2020-04-21 22:35:31

标签: list flutter dart tabbar provider

我正在尝试制作一个buttomtabbar,在第一个Tap页面上有一个列表(堆栈)。不知何故出现此错误,我只是不知道为什么... Screenshot with error warning

这是我的主文件:

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;
}

我认为问题就在上面的“正文: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)!!!

最新编辑:

因此,我的第一个Tap类现在是这样的(在首先声明了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类中。它说“在上下文中”和“错误:比较表达式不能是另一个比较表达式的操作数”下的“只能在初始化程序中访问静态成员”以及“错误:未为以下内容定义运算符'<”类'T Function(BuildContext,{listen:bool})'。”

也许您知道该怎么办。我想我把这条线放在错误的地方。

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

════════小部件库捕获到异常══════════════════════════════════ ═════════════════════ 在构建_BodyBuilder时引发了以下断言: _Tab1State.initState()完成之前,调用了dependentOnInheritedWidgetOfExactType>()或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(package: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 >>时引发了以下断言(脏,状态: 颤振:_DelegateWidgetState#eb784): flutter:尝试使用具有Listener / Stream(Stream>)子类型的Provider。 扑: 颤抖:这可能是一个错误,因为提供程序不会自动更新依赖项 颤动:更新Stream>时。相反,请考虑更改提供者以获取更具体的信息 flutter:处理更新机制的实现,例如: 扑: 扑:-ListenableProvider 扑:-ChangeNotifierProvider 颤抖:-ValueListenableProvider 扑:-StreamProvider 相关的引起错误的小部件是: 扑:供应商>> 颤抖:file:///Users/xxxxxxxxxxxx/AndroidStudioProjects/promi_prototype/lib/screens/my_tabs/tab1.dart:33:13

因此,tab1.dart中的提供程序仍然存在问题。我的猜测是更改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中创建一个吸气剂,这是我当时尝试的。但是没有成功。我在那里删除了吸气剂。

您有个主意吗?即使编译器说问题在tap1.dart中,更改AuftraegeList()中的Provider内容是否正确?

1 个答案:

答案 0 :(得分: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<DatabaseService>(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;
}

注意

  1. 在有状态窗口小部件中,BuildContext方法和initState方法中可以使用build。因此,您可以使用这些方法中的BuildContext,除非您隐式传递它。
  2. 如果您需要AuftragList()类中的列表,请获取一个实例 Provider.of<DatabaseService>(context)
  3. 中的列表
  4. 如果您需要列表在需要项可用时自动更新,则可以使用StreamSubscription来收听需求流并将其添加到列表中。
  5. 调用provider of时传递的是dataType而不是类。那是Provider.of<DatabaseService>(context)而不是Provider.of<DatabaseService()>(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();
      },

    );
  }
}

希望这行得通。