You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中Future<List<dynamic>?>列表显示与搜索重置问题

问题分析与解决方案

核心问题1:初始列表不显示/搜索功能失效

你当前的代码存在两个矛盾点:

  • 仅给allCandiesTypes赋值时,candyTypes初始为空,导致列表无数据显示;
  • 直接在FutureBuilder的builder方法中给candyTypes赋值时,每次组件重建(比如搜索触发setState)都会重新执行这段赋值逻辑,覆盖搜索后的过滤结果,导致搜索失效。

解决思路:把列表初始化逻辑从FutureBuilder的builder中移出,改用Future.then在数据加载完成后通过setState更新状态,避免每次组件重建都重置candyTypes。

修改CandyTypeSearchViewState的initState方法:

@override
void initState() {
  super.initState();
  // 在Future完成后初始化列表,避免builder重复赋值
  _candyTypes = viewModel.displayCandyTypeList().then((data) {
    if (mounted) {
      setState(() {
        allCandiesTypes = convertList(data);
        candyTypes = List.from(allCandiesTypes); // 初始显示全部数据
      });
    }
  });
}

修改candyTypeList的FutureBuilder逻辑,移除内部的列表赋值代码:

Widget candyTypeList() => FutureBuilder(
  future: _candyTypes,
  builder: (context, snapshot) {
    // 加载中/无数据状态
    if (snapshot.connectionState == ConnectionState.waiting || !snapshot.hasData) {
      return const Loader(loaderWidth: 30, loaderHeight: 30);
    }
    // 错误状态
    if (snapshot.hasError) {
      return ErrorText(errorMessage: snapshot.error.toString());
    }
    // 数据已加载完成,直接使用已初始化的candyTypes
    return ListView.builder(
      itemCount: candyTypes.length,
      itemBuilder: (context, index) {
        final candyType = candyTypes[index];
        return Column(
          children: [
            ListTile(
              title: Padding(
                padding: ThemeSize.paddingSymmetric(s, s),
                child: Text(
                  candyType.type!.toUpperCase(),
                  style: TextStyle(
                    color: ThemeColor.primary,
                    fontSize: ThemeSize.text(l),
                  ),
                ),
              ),
              onTap: () {
                Keyboard.sendFilterToFilterMenu(context, candyType.type!);
              },
            ),
            const Divider(height: 1, color: ThemeColor.borderGrey),
          ],
        );
      },
    );
  },
);

核心问题2:点击清除按钮无法重置列表

当前FilterSearchBar的清除按钮仅清空输入框,未通知父组件重置列表,需要新增回调实现该功能。

步骤1:修改FilterSearchBar,添加清除回调

class FilterSearchBar extends StatefulWidget {
  final String filterType;
  final TextEditingController searchController;
  final TextInputType keyboard;
  final ValueChanged<String>? onChanged;
  final VoidCallback? onClear; // 新增清除回调

  const FilterSearchBar({
    Key? key,
    required this.filterType,
    required this.searchController,
    required this.keyboard,
    this.onChanged,
    this.onClear, // 新增参数
  }) : super(key: key);

  @override
  State<FilterSearchBar> createState() => _FilterSearchBarState();
}

class _FilterSearchBarState extends State<FilterSearchBar> {
  bool showClearButton = false;

  @override
  void initState() {
    widget.searchController.addListener(() {
      setState(() {
        showClearButton = widget.searchController.text.isNotEmpty;
      });
    });
    super.initState();
  }

  @override
  void dispose() {
    widget.searchController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return TextFormField(
      keyboardType: widget.keyboard,
      controller: widget.searchController,
      onChanged: widget.onChanged,
      decoration: InputDecoration(
        border: const OutlineInputBorder(
            borderRadius: BorderRadius.all(Radius.circular(90.0)),
            borderSide: BorderSide(
              color: ThemeColor.white,
            )
        ),
        prefixIcon: const Icon(
          Icons.search_rounded,
          color: ThemeColor.gray600,
        ),
        hintStyle: TextStyle(
          color: ThemeColor.black,
          fontSize: ThemeSize.text(m),
          fontWeight: FontWeight.normal,
        ),
        suffixIcon: showClearButton ? IconButton(
          onPressed: clearSearchBar,
          icon: const Icon(
            Icons.close_outlined,
            color: ThemeColor.gray500,
          ),
        ) : null,
        filled: true,
        fillColor: ThemeColor.white,
        hintText: widget.filterType,
      ),
    );
  }

  void clearSearchBar() {
    widget.searchController.clear();
    widget.onClear?.call(); // 触发清除回调
  }
}

步骤2:在CandyTypeSearchView中绑定清除回调

FilterSearchBar(
  filterType: context.translation.searchCandy,
  searchController: searchController,
  keyboard: TextInputType.text,
  onChanged: searchCandyType,
  onClear: () { // 绑定清除逻辑
    setState(() {
      candyTypes = List.from(allCandiesTypes);
    });
  },
)

额外优化:处理搜索框为空的情况

修改searchCandyType方法,当输入为空时自动重置列表:

void searchCandyType(String query) {
  if (query.isEmpty) {
    setState(() {
      candyTypes = List.from(allCandiesTypes);
    });
    return;
  }
  suggestions = allCandiesTypes.where((candyType) {
    final candyTypeName = candyType.type!.toUpperCase().startsWith(query.toUpperCase());
    return candyTypeName;
  }).toList();
  setState(() => candyTypes = suggestions.isEmpty ? allCandiesTypes : suggestions);
}

内容的提问来源于stack exchange,提问作者Seth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 08:09:53