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

Flutter中如何向SharedPreferences存储完整对象列表而非单个变量

搜索历史功能修复方案

问题根源

你的代码存在几个关键问题导致只能保存单个搜索记录:

  • 语法错误导致逻辑执行异常(比如Final应为小写final、方法命名和参数不匹配)
  • SearchDelegateMenuPrincipal中初始化历史的方法未正确触发且未更新UI
  • 展示历史的组件中存在类型错误(直接访问字符串列表的apodo属性)

修复后的完整代码

class BBC extends StatefulWidget {
  @override
  State<BBC> createState() => _BBCState();
}

class _BBCState extends State<BBC> {
  List<SearchDelegateModel> historialMenuPrincipal = [];

  @override
  void initState() {
    super.initState();
    _cargarHistorial();
  }

  // 初始化加载本地存储的搜索历史
  Future<void> _cargarHistorial() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    List<String>? nombresHistorial = prefs.getStringList("HistorialBusquedaPreferences");
    if (nombresHistorial != null) {
      setState(() {
        historialMenuPrincipal = nombresHistorial.map((apodo) => SearchDelegateModel(apodo: apodo)).toList();
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        actions: [
          IconButton(
            icon: Icon(Icons.search),
            onPressed: () async {
              SharedPreferences prefs = await SharedPreferences.getInstance();
              final busqueda = await showSearch(
                context: context,
                delegate: SearchDelegateMenuPrincipal("Buscar...", historialMenuPrincipal)
              );
              if (busqueda != null) {
                setState(() {
                  // 移除重复记录
                  historialMenuPrincipal.removeWhere((item) => item.apodo == busqueda.apodo);
                  // 新记录插入到最前面
                  historialMenuPrincipal.insert(0, busqueda);
                });
                // 将完整的历史列表转成字符串列表存储
                List<String> nombres = historialMenuPrincipal.map((e) => e.apodo!).toList();
                await prefs.setStringList("HistorialBusquedaPreferences", nombres);
                // 打印完整历史列表验证
                var getpre = prefs.getStringList("HistorialBusquedaPreferences");
                print("完整搜索历史: $getpre");
              }
            },
          )
        ],
      ),
    );
  }
}

class SearchDelegateMenuPrincipal extends SearchDelegate<SearchDelegateModel> {
  List<SearchDelegateModel> historialMenuPrincipal;
  List<String> historialbusquedapreferences = [];

  SearchDelegateMenuPrincipal(String hintText, this.historialMenuPrincipal) : super(searchFieldLabel: hintText);

  @override
  void initState() {
    super.initState();
    _cargarHistorial();
  }

  Future<void> _cargarHistorial() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    historialbusquedapreferences = prefs.getStringList("HistorialBusquedaPreferences") ?? [];
    // 通知UI更新
    query = query;
  }

  @override
  Widget buildSuggestions(BuildContext context) {
    return historialbusquedapreferences.isEmpty
        ? MensajeHistorialBusquedaVacio()
        : HistorialBusqueda2(context, historialbusquedapreferences);
  }

  @override
  Widget buildLeading(BuildContext context) {
    return IconButton(
      icon: const Icon(Icons.arrow_back),
      onPressed: () => close(context, SearchDelegateModel(apodo: "")),
    );
  }

  @override
  Widget buildResults(BuildContext context) {
    // 根据你的需求实现搜索结果展示
    return Container();
  }
}

Widget HistorialBusqueda2(BuildContext context, List<String> historial) {
  return ListView.builder(
    itemCount: historial.length,
    itemBuilder: (context, i) {
      return ListTile(
        leading: Text(historial[i] ?? "no data"),
        onTap: () {
          // 点击历史记录时的逻辑
          (context as SearchDelegate).close(context, SearchDelegateModel(apodo: historial[i]));
        },
      );
    },
  );
}

Widget MensajeHistorialBusquedaVacio() {
  return Center(child: Text("暂无搜索历史"));
}

class SearchDelegateModel {
  String? apodo;
  String? name;

  SearchDelegateModel({this.apodo, this.name});

  factory SearchDelegateModel.fromJson(Map<String, dynamic> parsedJson) {
    return SearchDelegateModel(
      name: parsedJson['Name'],
      apodo: parsedJson['Apodo'],
    );
  }
}

关键修复点

  • 初始化加载历史:在BBC的initState和SearchDelegateMenuPrincipal的initState中分别加载本地存储的历史,确保页面打开时能显示已有记录
  • 修复语法错误:修正Final为final、方法命名空格问题、参数传递错误
  • 正确更新UI:使用setState更新本地列表,在SearchDelegate中通过更新query触发UI重建
  • 类型匹配:展示历史时直接使用字符串列表中的值,避免错误访问对象属性
  • 完整存储逻辑:每次添加新记录后,将完整的历史列表转成字符串列表存入SharedPreferences,而不是仅存单个值

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 11:53:21