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.

更多信息: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 设置为默认值并将列表设置为下拉菜单项

你应该检查必须在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;