Flutter DropdownButton动态默认值错误

问题描述 投票:0回答:1

我正在开发一个名为 Eleutherios 的开源项目,并不断收到此错误消息:

抛出了另一个异常:应该只有一个项目具有 [DropdownButton] 的值:ad7c17409ab11f249329c5528be5c5f7。

我从 firebase 填充 dropdownButton 并使用 initState 为最终用户预取所选注册者的默认 registrantId 并将其存储在 dropdownValue 中。

class _ViewForumScreenState extends ConsumerState<ViewForumScreen> {
    final messageController = TextEditingController();
    Registrant? selectedRegistrant;
    String? dropdownValue;
    var tapPosition;

    getSelectedRegistrant() async {
      final user = ref.read(userProvider)!;

      selectedRegistrant = await ref
          .read(getUserSelectedRegistrantProvider2(
              Tuple2(widget.forumId, user.uid)))
          .first;

      setState(() {
        dropdownValue = selectedRegistrant!.registrantId;
      });
    }

    @override
    void initState() {
      super.initState();
        WidgetsBinding.instance.addPostFrameCallback((_) {
          getSelectedRegistrant();
        }
      );
    }

然后使用 dropdownValue 作为 DropdownButton 的选定值。

Expanded(
    flex: 41,
    child: ref
        .watch(getUserRegistrantsProvider(
            Tuple2(widget.forumId, user.uid)))
        .when(
          data: (registrants) {
            return DropdownButtonHideUnderline(
              child: ButtonTheme(
                alignedDropdown: true,
                child: DropdownButton(
                  isDense: true,
                  value: dropdownValue,
                  onChanged: (String? registrantId) {
                    if (registrantId is String) {
                      changeSelectedRegistrant(
                          registrantId);
                    }
                  },
                  // *********************************
                  // items
                  // *********************************
                  items: registrants
                      .map<DropdownMenuItem<String>>(
                          (Registrant registrant) {
                            return ref
                                .watch(getServiceByIdProvider(
                                    registrant.serviceId))
                                .when(data: (service) {
                              return DropdownMenuItem<String>(
                                value: registrant.registrantId,
                                child: Row(children: [
                                  service!.image ==
                                          Constants
                                              .avatarDefault
                                      ? CircleAvatar(
                                          backgroundImage: Image
                                                  .asset(service
                                                      .image)
                                              .image,
                                          radius: 11,
                                        )
                                      : CircleAvatar(
                                          backgroundImage:
                                              NetworkImage(
                                                  service
                                                      .image),
                                          radius: 11,
                                        ),
                                  const SizedBox(
                                    width: 8,
                                  ),
                                  service.title.length > 12
                                      ? Text(
                                          '${service.title.substring(0, 12)}...',
                                          style:
                                              const TextStyle(
                                            fontSize: 14,
                                          ),
                                        )
                                      : Text(
                                          service.title,
                                          style:
                                              const TextStyle(
                                            fontSize: 14,
                                          ),
                                        ),
                                ]),
                              );
                            },
                            // *********************************
                            // error
                            // *********************************
                            error: (error, stackTrace) {
                              return DropdownMenuItem<String>(
                                value: error.toString(),
                                child: Text(error.toString()),
                              );
                            },
                            // *********************************
                            // loading
                            // *********************************
                            loading: () {
                              return const DropdownMenuItem<
                                  String>(
                                value: 'Loader',
                                child: Loader(),
                              );
                    });
                  }).toList(),
                ),
              ),
            );
          },
          error: (error, stackTrace) =>
              ErrorText(error: error.toString()),
          loading: () => const Loader(),
        ),
  ),

它可以工作,但颤动页面会瞬间呈红色闪烁,并显示上述错误消息。

奇怪的是,仅当我从抽屉(侧面板)页面导航到“查看论坛”页面时,才会出现错误。

在上图中你可以看到我打开侧图并点击体检论坛链接。

在上图中,您可以看到我收到错误消息。

如果我通过单击“论坛详细信息”页面中的“查看”按钮导航到“查看论坛”页面,则不会发生错误???

在上图中,在我单击“查看”按钮之前,您可以看到论坛详细信息页面。

这是没有错误的结果,一切正常。

以前有人遇到过这个问题并解决过吗?还是我遗漏了什么?

干杯!

列表抽奖页面代码:

https://github.com/aletheon/eleutherios-flutter/blob/main/lib/features/home/drawers/list_drawer.dart

论坛详情页面代码:

https://github.com/aletheon/eleutherios-flutter/blob/main/lib/features/forum/screens/forum_screen.dart

查看论坛页面的代码:

https://github.com/aletheon/eleutherios-flutter/blob/main/lib/features/forum/screens/view_forum_screen.dart

完整源代码:

https://github.com/aletheon/eleutherios-flutter

flutter dynamic dropdownbutton
1个回答
0
投票

问题出在这段代码上。

// *********************************
// items
// *********************************
items: registrants.map<DropdownMenuItem<String>>((Registrant registrant) {
  return ref
    .watch(getServiceByIdProvider(registrant.serviceId))
    .when(data: (service) {
      return DropdownMenuItem<String>(
        value: registrant.registrantId,
        child: Row(children: [...

我使用映射函数遍历注册者列表,然后立即调用该映射函数中的另一个提供程序来获取属于注册者的关联服务:

return ref.watch(getServiceByIdProvider(registrant.serviceId))

这会在调用 getServiceByIdProvider 时导致轻微延迟,并且我推测当 dropdownValue 有值时 DropdownButton 会稍微不同步。

因此,当进行比较时,列表中没有与 dropdownValue 匹配的关联值,因为 getServiceByIdProvider 尚未返回该值,因此会发生错误。

因此,将 getServiceByIdProvider 调用移动到 DropdownMenuItem 的子属性中就变得非常明显了。

像这样:

// *********************************
// items
// *********************************
items: registrants.map<DropdownMenuItem<String>>((Registrant registrant) {
  return DropdownMenuItem<String>(
    value: registrant.registrantId,
    child: ref
        .watch(getServiceByIdProvider(registrant.serviceId))
        .when(data: (service) {...

中提琴不再出错!

我知道这是一个菜鸟错误,但是嘿,正确地生活和学习。

:-)

© www.soinside.com 2019 - 2024. All rights reserved.