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

Flutter:如何将List<curso>存入SharedPreferences并读取展示?

解决SharedPreferences保存/读取多个curso对象列表并在ListView展示的问题

一、修改保存逻辑(支持添加多个课程到收藏列表)

当前代码仅能保存单个课程对象,要实现列表存储,需先读取已有收藏列表,添加新对象后再整体保存:

void saveCourseFavSP(String title,String entidad,String categoria,String emision,String imgcourse,String urlcourse,String idioma,String duracion,String description) async {
  SharedPreferences cursosFav = await SharedPreferences.getInstance();
  
  // 创建新的课程对象
  final newCurso = curso(
    title: title,
    entidad: entidad,
    categoria: categoria,
    emision: emision,
    imgcourse: imgcourse,
    urlcourse: urlcourse,
    idioma: idioma,
    duracion: duracion,
    description: description,
  );

  // 读取已有的收藏列表JSON
  String? existingJson = cursosFav.getString('coursesFavorites');
  List<Map<String, dynamic>> coursesList = [];

  if (existingJson != null) {
    // 将已有JSON解析为Map列表
    coursesList = List<Map<String, dynamic>>.from(jsonDecode(existingJson));
  }

  // 可选:检查课程是否已存在,避免重复添加
  bool isExist = coursesList.any((courseMap) => courseMap['title'] == title);
  if (!isExist) {
    // 将新课程转为Map加入列表
    coursesList.add(newCurso.toMap());
    // 保存更新后的列表JSON
    cursosFav.setString('coursesFavorites', jsonEncode(coursesList));
    print("课程已添加到收藏");
  } else {
    print("该课程已在收藏列表中");
  }
}

二、修改加载逻辑(读取整个收藏列表)

调整加载方法,将保存的列表JSON解析为List<curso>对象:

Future<List<curso>> loadDataCursosFavSP() async {
  SharedPreferences cursosFav = await SharedPreferences.getInstance();
  String? json = cursosFav.getString("coursesFavorites");
  
  if (json == null) {
    print("收藏列表为空");
    return [];
  } else {
    // 解析JSON为动态列表
    List<dynamic> jsonList = jsonDecode(json);
    // 将每个Map转为curso对象
    List<curso> coursesList = jsonList.map((map) => curso.fromMap(map)).toList();
    print("成功加载${coursesList.length}个收藏课程");
    return coursesList;
  }
}

三、在ListView中展示收藏列表

使用FutureBuilder处理异步加载,配合ListView.builder渲染列表:

class FavoritesScreen extends StatefulWidget {
  const FavoritesScreen({super.key});

  @override
  State<FavoritesScreen> createState() => _FavoritesScreenState();
}

class _FavoritesScreenState extends State<FavoritesScreen> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("我的收藏课程")),
      body: FutureBuilder<List<curso>>(
        future: loadDataCursosFavSP(),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            return const Center(child: CircularProgressIndicator());
          } else if (snapshot.hasError) {
            return Center(child: Text("加载失败: ${snapshot.error}"));
          } else if (!snapshot.hasData || snapshot.data!.isEmpty) {
            return const Center(child: Text("暂无收藏课程"));
          } else {
            return ListView.builder(
              itemCount: snapshot.data!.length,
              itemBuilder: (context, index) {
                curso course = snapshot.data![index];
                return ListTile(
                  leading: Image.network(course.imgcourse, width: 50, height: 50, fit: BoxFit.cover),
                  title: Text(course.title),
                  subtitle: Text("机构: ${course.entidad} | 时长: ${course.duracion}"),
                  // 可根据需求添加点击事件或更多展示内容
                );
              },
            );
          }
        },
      ),
    );
  }
}

四、关键注意事项

  • 列表维护逻辑:不能直接覆盖单个对象,必须先读取已有列表数据,添加新对象后再整体保存
  • 去重处理:可通过课程唯一标识(如title)判断是否已存在,根据业务需求调整规则
  • 异步状态处理:加载数据为异步操作,需用FutureBuilder或在initState中预加载数据后更新状态
  • JSON转换规则:保存时先将每个curso转为Map,再将Map列表转为JSON字符串;读取时反向解析即可

内容的提问来源于stack exchange,提问作者Carlos Peñaranda

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 15:26:07