Flutter DropDownMenu:初始化默认值异步
Flutter DropDownMenu: Initialize default value async
我们有一个 flutter 项目 运行 并且想要包含一个带有下拉菜单的有状态小部件。我们使用 SQflite 作为我们的数据库。
我们的数据库中有一个配置文件列表,我们希望通过下拉菜单 select 其中一个配置文件。这很好用。
问题:
我们使用 SharedPreferences select 保存最后一个配置文件的 ID。最初我们希望将最后一个 selected id(我们从 SharedPreferences 加载)的配置文件作为默认值。
我们在未来构建器中的下拉菜单(列表 profilesFuture
类型 Future<List<Profile>>
):
return new Container(
child: DropdownButton<Profile>(
items: snapshot.data.map((Profile item) {
return DropdownMenuItem<Profile>(
value: item,
child: Text(item.caption + " (" + item.serverAddress + ")")
);
}).cast<DropdownMenuItem<Profile>>().toList(),
onChanged: (Profile newSelectedProfile) {
setState(() {
selectedProfile = newSelectedProfile;
PreferencesService.setLastProfileId(newSelectedProfile.id);
});
},
value: selectedProfile,
)
);
我们这样初始化我们的状态:
Future profilesFuture;
Profile selectedProfile;
Future prefService;
int lastProfileId;
@override
void initState() {
profilesFuture = DatabaseService.db.getProfiles();
super.initState();
_getLastProfileId().then((value) => _getSelectedProfile(value));
}
Future<Profile> _getSelectedProfile(int id) async {
Profile profile = await DatabaseService.db.getProfileById(id);
setState(() {
selectedProfile = profile;
});
return profile;
}
Future<int> _getLastProfileId() async {
int profileId = await PreferencesService.getLastProfileId();
setState(() {
lastProfileId = profileId;
});
return profileId;
}
错误
either zero or 2 or more dropdownmenuitems were detected with the same value. Assertion failed. There should be exactly one item with DropDownMenus value.
问题
有什么问题吗?如何使用异步值正确初始化 DropDownMenu。问题肯定是由默认值引起的。没有初始化值参数它工作正常,但初始状态不正确。
我们所要做的就是:
- 从 SharedPreferences 加载 lastSelectedProfileId(异步)
- 从数据库层(异步)加载 selectedProfile
- 从数据库层加载所有配置文件的列表(异步)
- 将 selectedProfile 设置为默认值并将列表设置为下拉菜单项
你应该检查值必须在items.value。您需要在下拉列表中检查的内容
List<DropdownMenuItem<String>> _bankAccountType = [
DropdownMenuItem(child: Text("--"), value: "--"),
DropdownMenuItem(child: Text("Checking"), value: "Checking"),
DropdownMenuItem(child: Text("Savings"), value: "Savings"),
];
DropdownButton<String>(
items: _bankAccountType,
iconSize: 0.0,
value: _bankAccountTypeValue,
onChanged: (value) {
setState(() {
_bankAccountTypeValue = value;
});
_checkBankAccountFormStatus();
}
),
这将帮助您解决问题。
参考@pskink这是解决我们问题的解决方案:
我们已经覆盖了数据模型中的默认 ==
操作 Profile
。
bool operator == (dynamic other) =>
other != null && other is Profile && this.id == other.id;
@override
int get hashCode => super.hashCode;
我们有一个 flutter 项目 运行 并且想要包含一个带有下拉菜单的有状态小部件。我们使用 SQflite 作为我们的数据库。
我们的数据库中有一个配置文件列表,我们希望通过下拉菜单 select 其中一个配置文件。这很好用。
问题:
我们使用 SharedPreferences select 保存最后一个配置文件的 ID。最初我们希望将最后一个 selected id(我们从 SharedPreferences 加载)的配置文件作为默认值。
我们在未来构建器中的下拉菜单(列表 profilesFuture
类型 Future<List<Profile>>
):
return new Container(
child: DropdownButton<Profile>(
items: snapshot.data.map((Profile item) {
return DropdownMenuItem<Profile>(
value: item,
child: Text(item.caption + " (" + item.serverAddress + ")")
);
}).cast<DropdownMenuItem<Profile>>().toList(),
onChanged: (Profile newSelectedProfile) {
setState(() {
selectedProfile = newSelectedProfile;
PreferencesService.setLastProfileId(newSelectedProfile.id);
});
},
value: selectedProfile,
)
);
我们这样初始化我们的状态:
Future profilesFuture;
Profile selectedProfile;
Future prefService;
int lastProfileId;
@override
void initState() {
profilesFuture = DatabaseService.db.getProfiles();
super.initState();
_getLastProfileId().then((value) => _getSelectedProfile(value));
}
Future<Profile> _getSelectedProfile(int id) async {
Profile profile = await DatabaseService.db.getProfileById(id);
setState(() {
selectedProfile = profile;
});
return profile;
}
Future<int> _getLastProfileId() async {
int profileId = await PreferencesService.getLastProfileId();
setState(() {
lastProfileId = profileId;
});
return profileId;
}
错误
either zero or 2 or more dropdownmenuitems were detected with the same value. Assertion failed. There should be exactly one item with DropDownMenus value.
问题
有什么问题吗?如何使用异步值正确初始化 DropDownMenu。问题肯定是由默认值引起的。没有初始化值参数它工作正常,但初始状态不正确。
我们所要做的就是:
- 从 SharedPreferences 加载 lastSelectedProfileId(异步)
- 从数据库层(异步)加载 selectedProfile
- 从数据库层加载所有配置文件的列表(异步)
- 将 selectedProfile 设置为默认值并将列表设置为下拉菜单项
你应该检查值必须在items.value。您需要在下拉列表中检查的内容
List<DropdownMenuItem<String>> _bankAccountType = [
DropdownMenuItem(child: Text("--"), value: "--"),
DropdownMenuItem(child: Text("Checking"), value: "Checking"),
DropdownMenuItem(child: Text("Savings"), value: "Savings"),
];
DropdownButton<String>(
items: _bankAccountType,
iconSize: 0.0,
value: _bankAccountTypeValue,
onChanged: (value) {
setState(() {
_bankAccountTypeValue = value;
});
_checkBankAccountFormStatus();
}
),
这将帮助您解决问题。
参考@pskink这是解决我们问题的解决方案:
我们已经覆盖了数据模型中的默认 ==
操作 Profile
。
bool operator == (dynamic other) =>
other != null && other is Profile && this.id == other.id;
@override
int get hashCode => super.hashCode;