Error:
Failed assertion: line 609 pos 15: 'items == null ||
I/flutter (24295): items.isEmpty || value == null || items.where((DropdownMenuItem<T> item) => item.value ==
I/flutter (24295): value).length == 1': is not true.
I did some research and did not figure out what caused the problem. Here is my code:
class StatusList extends StatefulWidget {
@override
_StatusListState createState() => _StatusListState();
}
class _DispositionListState extends State<DispositionList> {
var _currentSelectedValue = '';
Future<RecordList> recordList;
@override
void initState() {
recordList = getRecord();
super.initState();
}
int i = 1;
List<String> statusList = List<String>();
@override
Widget build(BuildContext context) {
return FutureBuilder<RecordList>(
future: recordList,
builder: (context, snapshot) {
if (snapshot.hasData) {
String current = snapshot.data.record[0].status.trim();
statusList.add(snapshot.data.record[0].status.trim());
while (i < snapshot.data.record.length) {
if (snapshot.data.record[i].status.trim() != current) {
statusList.add(snapshot.data.record[i].status.trim());
current = snapshot.data.record[i].status.trim();
}
i++;
}
_currentSelectedValue = statusList[0]; //not set this will straight getting error
return DropdownButton(
items: statusList.map((String dropDownStringItem) {
return DropdownMenuItem<String>(
value: dropDownStringItem,
child: SizedBox(
width: 200.0,
child: Text(
dropDownStringItem,
overflow: TextOverflow.ellipsis,
),
));
}).toList(),
onChanged: (String valueSelected) {
onDropDownSelected(valueSelected);
},
value: _currentSelectedValue,
);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
return CircularProgressIndicator();
});
}
void onDropDownSelected(String valueSelected) {
setState(() {
this._currentSelectedValue = valueSelected;
});
}
}
I tried compare the recordList and the valueSelected in onDropDownSelected return true. Problem caused when the setState is called even without any code inside. Anyone idea of what caused the problem based on these code?
Added code: Here is my getRecord()
Future<RecordList> getRecord() async {
String url = 'some url';
final response = await http.get(url, headers: {"Accept": "application/json"});
if (response.statusCode == 200) {
return RecordList.fromJson(json.decode(response.body));
} else {
throw Exception('Failed to load post');
}
}
class Record {
final String status;
final String disposition;
final int total;
Record({this.status, this.disposition, this.total});
factory Record.fromJson(Map<String, dynamic> json) {
return Record(
status: json['status'],
disposition: json['disposition'],
total: json['total']);
}
}
class RecordList {
final List<Record> record;
RecordList({this.record});
factory RecordList.fromJson(List<dynamic> parsedJson) {
List<Record> record = new List<Record>();
record = parsedJson.map((i) => Record.fromJson(i)).toList();
return new RecordList(
record: record,
);
}
}
It can be that the value
property of DropdownButton
has the value which is not one of item
's value. value
property should be either null
or one of the item's value.
Also, maybe you don't need a FutureBuilder
here. You can do something like that:
class _DispositionListState extends State<DispositionList> {
bool _isLoading = true;
String _currentSelectedValue;
List<String> statusList = List<String>();
@override
void initState() {
super.initState();
_loadStatusList();
}
_loadStatusList() async {
final recordList = await getRecord();
final list = recordList.record.map((r) {
return r.status.trim();
}).toSet().toList();
setState(() {
statusList = list;
_currentSelectedValue = list.first;
_isLoading = false;
});
}
@override
Widget build(BuildContext context) {
return isLoading ? CircularProgressIndicator() : _buildDropdown();
}
Widget _buildDropdown() {
return DropdownButton(
items: statusList.map((dropDownStringItem) {
return DropdownMenuItem<String>(
value: dropDownStringItem,
child: SizedBox(
width: 200.0,
child: Text(
dropDownStringItem,
overflow: TextOverflow.ellipsis,
),
),
);
}).toList(),
onChanged: (valueSelected) {
onDropDownSelected(valueSelected);
},
value: _currentSelectedValue,
);
}
void onDropDownSelected(String valueSelected) {
setState(() {
this._currentSelectedValue = valueSelected;
});
}
}
Update: Added
.toSet()
to filter out duplicates fromstatusList
I think the problem is that the status list has duplicated items. I added .toSet()
before .toList()
to filter out duplicates. Set
is a collection of objects in which each object can occur only once.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.