类型‘ List < Dynamic >’不是类型‘ List < Widget >’的子类型

我有一个代码片段,我从 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>'

这里出了什么问题?

169169 次浏览

这里的问题是类型推断会以意想不到的方式失败。解决方案是为 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,也可能是因为无法对闭包的返回值进行类型注释。

我已经通过将 Map转换为 Widget来解决我的问题

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

可以使用特定类型将动态列表强制转换为列表:

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

我认为在某些小部件的 孩子们属性中使用 _ buildBody,因此 孩子们期望有一个 列表小部件(Widget 数组) ,而 _ buildBody 返回一个 < em > ‘ List Dynamic’

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

// 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
)

例子(颤振产生 test1; Cd 测试1; 编辑 lib/main.dart; 颤振跑) :

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'.");},
);
}
}

我做了一个 完整的例子,我使用 动态窗口小部件来显示和隐藏小部件在屏幕上,你可以看到它在线运行的 飞镖小提琴,也。

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

这对我有用

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

我有一个字符串列表,我试图在我的应用程序中读取。当我试图将它强制转换为 List of String 时,也出现了同样的错误。

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

例如:

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

我认为,在把 List 的类型从 Dynamic 改为 String & doing 重新装弹之后,就会出现这个错误,热重启是解决方案。

请记住: 热重启只重建 build ()函数,而不是整个类 & 声明列表在类的顶部是在 build ()函数之外

我的解决方案是,你可以将 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(),
);