[英]Selection of Item in DropdownButton causes Flutter to throw error
我目前正在尝试从REST API检索数据(标签),并使用该数据填充一个可以成功完成的下拉菜单,但是在选择该项目时,出现以下错误,根据该错误, 这意味着“已选择”值不是值列表的成员”:
项目== null || 值== null || items.where(((DropdownMenuItem item)=> item.value == value).length == 1':不正确。
这是在下拉菜单显示我的选定项目之后发生的。 但是,这不是应该发生的错误,因为我已经完成了必要的日志记录,以检查数据是否确实分配给了相关列表。 谁能帮我解决这个问题? 我已经将其隔离到起源于DropdownButton的onChanged
的setState()
方法,但是似乎无法理解为什么这会引起问题。 任何帮助将不胜感激!
我的代码如下:
class _TodosByTagsHomePageState extends State<TodosByTagsHomePage> {
Tag selectedTag;
final Logger log = new Logger('TodosByTags');
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Second Screen"),
),
body: ListView(
children: <Widget>[
FutureBuilder<List<Tag>> (
future: fetchTags(),
builder: (context, snapshot) {
if (snapshot.hasData) {
log.info("Tags are present");
_tagsList = snapshot.data;
return DropdownButton<Tag>(
value: selectedTag,
items: _tagsList.map((value) {
return new DropdownMenuItem<Tag>(
value: value,
child: Text(value.tagName),
);
}).toList(),
hint: Text("Select tag"),
onChanged: (Tag chosenTag) {
setState(() {
log.info("In set state");
selectedTag = chosenTag;
Scaffold.of(context).showSnackBar(new SnackBar(content: Text(selectedTag.tagName)));
});
},
) ;
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
return Container(width: 0.0, height: 0.0);
}),
])
);
}
// Async method to retrieve data from REST API
Future<List<Tag>> fetchTags() async {
final response =
await http.get(REST_API_URL);
if (response.statusCode == 200) {
// If the call to the server was successful, parse the JSON
var result = compute(parseData, response.body);
return result;
} else {
// If that call was not successful, throw an error.
throw Exception('Failed to load post');
}
}
static List<Tag> parseData(String response) {
final parsed = json.decode(response);
return (parsed["data"] as List).map<Tag>((json) =>
new Tag.fromJson(json)).toList();
}
List<Tag> _tagsList = new List<Tag>();
}
// Model for Tag
class Tag {
final String tagName;
final String id;
final int v;
Tag({this.id, this.tagName, this.v});
factory Tag.fromJson(Map<String, dynamic> json) {
return new Tag(
id: json['_id'],
tagName: json['tagName'],
v: json['__v'],
);
}
}
这样更新代码,我认为这样的问题是,在FutureBuilder
中调用setState
并调用fetchTags()
将fetchTags()
移至initState()
一次即可调用
class _TodosByTagsHomePageState extends State<TodosByTagsHomePage> {
Tag selectedTag;
Future<List<Tag>> _tags;
@override
void initState() {
_tags = fetchTags();
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Second Screen"),
),
body: ListView(children: <Widget>[
FutureBuilder<List<Tag>>(
future: _tags,
builder: (context, snapshot) {
if (snapshot.hasData) {
return DropdownButton<Tag>(
value: selectedTag,
items: snapshot.data.map((value) {
print(value);
return DropdownMenuItem<Tag>(
value: value,
child: Text(value.tagName),
);
}).toList(),
hint: Text("Select tag"),
onChanged: (Tag chosenTag) {
setState(() {
selectedTag = chosenTag;
});
},
);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
return Container(width: 0.0, height: 0.0);
}),
]));
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.