【问题标题】:type 'List<dynamic>' is not a subtype of type 'List<Widget>''List<dynamic>' 类型不是 'List<Widget>' 类型的子类型
【发布时间】:2018-09-11 04:23:35
【问题描述】:

我有一段从 Firestore 示例复制的代码:

Widget _buildBody(BuildContext context) {
    return new StreamBuilder(
      stream: _getEventStream(),
      builder: (context, snapshot) {
        if (!snapshot.hasData) return new Text('Loading...');
        return new ListView(
          children: snapshot.data.documents.map((document) {
            return new ListTile(
              title: new Text(document['name']),
              subtitle: new Text("Class"),
            );
          }).toList(),
        );
      },
    );
  }

但我得到了这个错误

type 'List<dynamic>' is not a subtype of type 'List<Widget>'

这里出了什么问题?

【问题讨论】:

    标签: firebase flutter dart google-cloud-firestore


    【解决方案1】:

    这里的问题是类型推断以意想不到的方式失败。解决方案是为map 方法提供一个类型参数。

    snapshot.data.documents.map<Widget>((document) {
      return new ListTile(
        title: new Text(document['name']),
        subtitle: new Text("Class"),
      );
    }).toList()
    

    更复杂的答案是,虽然children 的类型是List&lt;Widget&gt;,但该信息不会流回map 调用。这可能是因为map 后面跟着toList,并且没有办法对闭包的返回进行类型注解。

    【讨论】:

    • 可能与使用 Dart 2 的强模式或颤振有关。
    • 这个特定的变化可能与动态相关,也就是底部的“模糊箭头”——以前可以将 List 分配给 List。这掩盖了很多推理空白。
    • TBH 我还没有设法重现他的错误。由于他的代码被推断为List&lt;ListTile&gt;,即使没有将其指定为map
    • 很好解决了这个问题。但这有点奇怪,我是飞镖新手,所以我不能说我理解它。
    • 我遇到了同样的问题(但我的情况不同)。我认为这是因为 Dart 2 强类型。一旦我将变量声明更改为 List 它就开始工作了。
    【解决方案2】:

    您可以将动态列表转换为具有特定类型的列表:

    List<'YourModel'>.from(_list.where((i) => i.flag == true));
    

    【讨论】:

      【解决方案3】:

      我通过将Map 转换为Widget 解决了我的问题

            children: snapshot.map<Widget>((data) => 
                     _buildListItem(context, data)).toList(),
      

      【讨论】:

      • 谢谢你这么简单的回答!
      • 为什么它不适合我?飞镖零安全
      【解决方案4】:

      我在 firestore 中有一个字符串列表,我试图在我的应用程序中读取它。当我尝试将其转换为字符串列表时,我遇到了同样的错误。

      type 'List<dynamic>' is not a subtype of type 'List<Widget>'
      

      这个解决方案帮助了我。看看吧。

      var array = document['array']; // array is now List<dynamic>
      List<String> strings = List<String>.from(array);
      

      【讨论】:

        【解决方案5】:

        我认为您在某些小部件的 children 属性中使用了 _buildBody,因此 children 期望 List Widget(小部件数组)和_buildBody 返回一个“动态列表”

        一种非常简单的方式,你可以使用一个变量来返回它:

        // you can build your List of Widget's like you need
        List<Widget> widgets = [
          Text('Line 1'),
          Text('Line 2'),
          Text('Line 3'),
        ];
        
        // you can use it like this
        Column(
          children: widgets
        )
        

        示例(flutter create test1 ; cd test1 ; edit lib/main.dart ; flutter run) :

        import 'package:flutter/material.dart';
        
        void main() {
          runApp(MyApp());
        }
        
        class MyApp extends StatefulWidget {
          @override
          _MyAppState createState() => _MyAppState();
        }
        
        class _MyAppState extends State<MyApp> {
          List<Widget> widgets = [
            Text('Line 1'),
            Text('Line 2'),
            Text('Line 3'),
          ];
        
          Widget build(BuildContext context) {
            return MaterialApp(
              home: Scaffold(
                appBar: AppBar(title: Text("List of Widgets Example")),
                body: Column(
                  children: widgets
                )
              )
            );
          }
        
        }
        

        小部件列表(arrayOfWidgets) 中使用小部件 (oneWidget) 的另一个示例。我展示了一个小部件(MyButton)如何个性化小部件并减少代码大小:

        import 'package:flutter/material.dart';
        
        void main() {
          runApp(MyApp());
        }
        
        class MyApp extends StatefulWidget {
          @override
          _MyAppState createState() => _MyAppState();
        }
        
        class _MyAppState extends State<MyApp> {
          List<Widget> arrayOfWidgets = [
            Text('My Buttons'),
            MyButton('Button 1'),
            MyButton('Button 2'),
            MyButton('Button 3'),
          ];
        
          Widget oneWidget(List<Widget> _lw) { return Column(children: _lw); }
        
          Widget build(BuildContext context) {
            return MaterialApp(
              home: Scaffold(
                appBar: AppBar(title: Text("Widget with a List of Widget's Example")),
                body: oneWidget(arrayOfWidgets)
              )
            );
          }
        
        }
        
        class MyButton extends StatelessWidget {
          final String text;
        
          MyButton(this.text);
        
          @override
          Widget build(BuildContext context) {
            return FlatButton(
              color: Colors.red,
              child: Text(text),
              onPressed: (){print("Pressed button '$text'.");},
            );
          }
        }
        

        我做了一个完整示例,我使用dynamic widgets在屏幕上显示和隐藏小部件,您也可以在dart fiddle上看到它在线运行。

        import 'package:flutter/material.dart';
        
        void main() {
          runApp(MyApp());
        }
        
        class MyApp extends StatefulWidget {
          @override
          _MyAppState createState() => _MyAppState();
        }
        
        class _MyAppState extends State<MyApp> {
          List item = [
            {"title": "Button One", "color": 50},
            {"title": "Button Two", "color": 100},
            {"title": "Button Three", "color": 200},
            {"title": "No show", "color": 0, "hide": '1'},
          ];
        
          Widget build(BuildContext context) {
            return MaterialApp(
              home: Scaffold(
                appBar: AppBar(title: Text("Dynamic Widget - List<Widget>"),backgroundColor: Colors.blue),
                body: Column(
                  children: <Widget>[
                    Center(child: buttonBar()),
                    Text('Click the buttons to hide it'),
                  ]
                )
              )
            );
          }
        
          Widget buttonBar() {
            return Column(
              children: item.where((e) => e['hide'] != '1').map<Widget>((document) {
                return new FlatButton(
                  child: new Text(document['title']),
                  color: Color.fromARGB(document['color'], 0, 100, 0),
                  onPressed: () {
                    setState(() {
                      print("click on ${document['title']} lets hide it");
                      final tile = item.firstWhere((e) => e['title'] == document['title']);
                      tile['hide'] = '1';
                    });
                  },
                );
              }
            ).toList());
          }
        }
        

        也许它可以帮助某人。如果它对您有用,请让我知道单击向上箭头。谢谢。

        https://dartpad.dev/b37b08cc25e0ccdba680090e9ef4b3c1

        【讨论】:

        • 这似乎不再起作用。不能分配例如Text('My Buttons')List&lt;Widget&gt; 数组中。获取The element type 'Text' can't be assigned to the list type 'Widget'。有什么办法可以解决这个问题?
        • 文本是一个Widget,可以是List的一个元素。检查此垫https://dartpad.dev/6a908fe99f604474fd052731d59d059c 并告诉我它是否适合您。
        • "元素类型 'List' 不能分配给列表类型 'Widget'。"从你的第一个例子开始。好像没用了
        【解决方案6】:

        这对我有用List&lt;'YourModel'&gt;.from(_list.where((i) =&gt; i.flag == true));

        【讨论】:

          【解决方案7】:

          要将每个项目转换为小部件,请使用ListView.builder() 构造函数。

          一般来说,提供一个构建器函数来检查您正在处理的项目类型,并为该类型的项目返回适当的小部件。

          ListView.builder(
            // Let the ListView know how many items it needs to build.
            itemCount: items.length,
            // Provide a builder function. This is where the magic happens.
            // Convert each item into a widget based on the type of item it is.
            itemBuilder: (context, index) {
              final item = items[index];
          
              return ListTile(
                title: item.buildTitle(context),
                subtitle: item.buildSubtitle(context),
              );
            },
          );
          

          【讨论】:

            【解决方案8】:

            通过添加 .toList() 更改为列表解决了问题

            【讨论】:

              【解决方案9】:

              有一条关于声明您的列表的评论 而不是“List myList = [1,2,3]”

              声明到“列表”“myList [1,2,3]”

              可以确认这解决了 type 'List' is not a subtype of type 'List' 的错误

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2021-11-09
                • 2021-05-17
                • 1970-01-01
                • 2021-01-10
                • 2021-01-10
                • 1970-01-01
                • 2020-12-10
                相关资源
                最近更新 更多