Following code fills a DropdownButtonFormField with items (initial selection is null), when user selects a selections which is i.e. index of 15. All works ok so far. "Suddenly" Streambuilder refreshs list with less items than 15, lets say 10. And tries to "redraw" the dropdownButtonFormField and provides another index (null or 0), code suddenly fails with following:
How do I reliably change the selected value to less than provided list, when it seems that my new value is not taken into consideration ? Or is there a bug in DropdownButtonFormField according to changing the selected value?
Expanded(
child: Padding(
padding: const EdgeInsets.all(4.0),
child: StreamBuilder(
stream: globals.mPortalDatabase.getGoogleAddresses().watch(),
builder: (context, snapshot) {
if(snapshot.hasError){
return DropdownButtonFormField<int>(
decoration: InputDecoration(
label: Text("Assignment location"),
border: OutlineInputBorder()
),
items: [
DropdownMenuItem(child: Text(snapshot.error.toString(), style: TextStyle(color: Colors.red),))
],
onChanged: null,
);
}
if(snapshot.connectionState==ConnectionState.waiting){
return DropdownButtonFormField<int>(
decoration: InputDecoration(
label: Text("Assignment location"),
border: OutlineInputBorder()
),
items: [],
onChanged: null,
);
}
List<DropdownMenuItem<int>> dropdownMenuItemList=[];
if(snapshot.hasData){
var googleDataElements = snapshot.data;
print("Data present for dropdown = ${googleDataElements?.length}");
if(googleDataElements!=null){
if(googleDataElements.isNotEmpty){
dropdownMenuItemList = List.generate(googleDataElements.length, (index) {
return DropdownMenuItem<int>(
child: Text("${googleDataElements[index].formattedAddress}; ${googleDataElements[index].geometryLocationType}"),
value: index,
);
});
}
if(selectedAddressIndex!=null){
if(selectedAddressIndex!<dropdownMenuItemList.length){
if(googleDataElements[selectedAddressIndex!].formattedAddress!=selectedAddressItem){
selectedAddressIndex = null;
}
} else {
selectedAddressIndex = null;
}
}
} else {
selectedAddressIndex = null;
}
} else {
print("No data present for dropdown");
}
print("Data present for dropdown = ${dropdownMenuItemList.length}");
print("selectedAddressIndex = $selectedAddressIndex");
return DropdownButtonFormField<int>(
value: selectedAddressIndex,
decoration: InputDecoration(
label: Text("Assignment location"),
border: OutlineInputBorder(),
),
items: dropdownMenuItemList,
onChanged: (value){
}
);
}
),
),
),
Typical log content, as you see, the selectedAddressIndex is changed, but fails anyway...:


Flutter is not detecting that your
DropdownButtonFormFieldwidget has changed when it is rebuilding the tree. It can be fixed by providing a Key to your widget which shall change when the stream returns new data.The easiest way is creating a
ValueKeycreated with unique values from the list of elements, for example:And then provide that key in the constructor of the
DropdownButtonFormFieldwidget.