类型“List<dynamic>”不是类型“List<Widget>”的子类型

问题描述 投票:0回答:12

我有一段从 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
12个回答
421
投票

这里的问题是类型推断以意想不到的方式失败。解决方案是为

map
方法提供类型参数。

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

更复杂的答案是,虽然

children
的类型是
List<Widget>
,但该信息不会流回
map
调用。这可能是因为
map
后面跟着
toList
并且因为无法键入注释闭包的返回。


63
投票

我在 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);

37
投票

您可以将动态列表投射到具有特定类型的列表:

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

32
投票

我通过将

Map
转换为
Widget

解决了我的问题
children: snapshot.map<Widget>((data) => 
    _buildListItem(context, data)).toList(),

8
投票

我的解决方案是,您可以将

List<dynamic>
转换为
List<Widget>
,您可以在
snapshot.data.documents.map
后添加一个简单的代码到
snapshot.data.documents.map<Widget>
,就像我将在下面向您展示的代码

从这里

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

进入这个

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

7
投票

我认为您在某些小部件的 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 test1cd test1edit lib/main.dartflutter 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
        )
      )
    );
  }

}

另一个在 Widgets 列表(arrayOfWidgets) 中使用 Widget (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'.");},
    );
  }
}

我做了一个完整的例子,我使用动态小部件在屏幕上显示和隐藏小部件,你也可以看到它在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


4
投票

这对我有用

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


4
投票

示例:

List<dynamic> listOne = ['111','222']
List<String> ListTwo = listOne.cast<String>();

2
投票

我认为,将 List 的类型从动态更改为 String 并执行热重载后会出现此错误,热重启是解决方案..

记住:热重启仅重建 build() 函数,而不是整个类并且声明类顶部的 List 位于 build() 函数之外


1
投票

通过添加

.toList()
更改为列表解决了问题


1
投票

改变

List list = [];

对此:

List<Widget> list = [];

解决了我的问题!!


0
投票

错误消息 type 'List' is not a subtype of type 'List' in typecast 表示您正在尝试将 List 转换为 List

List<dynamic> dynamicList = ['apple', 'banana', 'cherry'];
List<String> stringList = dynamicList.map((e) => e.toString()).toList();
© www.soinside.com 2019 - 2024. All rights reserved.