Flutter DropDownMenu:初始化异步默认值

问题描述

我们正在运行一个Flutter-project,并希望包含一个带下拉菜单的有状态小部件。我们使用SQflite作为我们的数据库

我们在数据库中有一个配置文件列表,并通过下拉菜单选择一个配置文件效果很好。

问题:

我们使用SharedPreferences保存最后选择的配置文件的ID。最初,我们希望将配置文件的最后一个选定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.

更多信息:https://github.com/glutter-dev-team/glutter/blob/feature/profile-selector/lib/widgets/profile_selector.dart

问题

这有什么问题?如何使用异步值正确初始化DropDownMenu。该问题肯定是由认值引起的。不初始化值参数就可以正常工作,但是初始状态不正确。

我们要做的就是:

  1. 从SharedPreferences中加载lastSelectedProfileId(异步)
  2. 数据库层(异步)加载selectedProfile
  3. 数据库层(异步)加载所有配置文件的列表
  4. 将selectedProfile设置为认值,并将列表设置为下拉菜单

解决方法

请参阅@pskink,这是解决了我们问题的解决方案:

我们已经覆盖了数据模型GenericAdapter<String,NotificationFragmentBinding> transmissionAdapter; transmissionAdapter = new GenericAdapter<String,NotificationFragmentBinding>(getContext(),carsList) { @Override public int getLayoutResId() { return 0; } @Override public void onBindData(String model,int position,NotificationFragmentBinding dataBinding) { } @Override public void onItemClick(String model,int position) { } } 中的默认 var notificationGenericAdapter: GenericAdapter<String,NotificationFragmentBinding>? = null notificationGenericAdapter = object : GenericAdapter<String?,NotificationFragmentBinding?>(this,list) { override fun getLayoutResId(): Int { return 0 } override fun onBindData(model: String?,position: Int,dataBinding: NotificationFragmentBinding?) {} override fun onItemClick(model: String?,position: Int) {} } 操作。

==
,

您应该在 items.value 中选中 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();
                      }
                  ),

这将帮助您解决问题。