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

Flutter中如何用ExpansionTile和ListView展示SQLite数据

问题解决思路与实现方案

一、_getData调用的常见问题排查

  • 若在initState中调用_getData,必须在数据获取完成后通过setState更新UI——SQLite操作是异步的,不触发状态更新的话UI不会刷新
  • 绝对不能在build方法里直接调用_getData,这会导致每次组件重建都重复查询数据库,引发无限循环

二、核心实现步骤

1. 数据库查询逻辑调整

在DBHelper中实现全量教师数据查询(后续在内存中分组,比多次查询更高效):

// DBHelper类中的方法
Future<List<Map<String, dynamic>>> getAllTeachers() async {
  Database db = await this.database;
  return await db.query('teachers');
}

2. 数据分组与Fields类映射

在_getData方法中,将查询结果按section分组,再转成Fields类的列表:

// 假设你的Fields类结构如下
class Fields {
  final String section;
  final List<String> dataList;

  Fields(this.section, this.dataList);
}

List<Fields> _sectionTeachers = [];

Future<void> _getData() async {
  List<Map<String, dynamic>> rawTeachers = await DBHelper().getAllTeachers();
  
  // 按section分组存储教师姓名
  Map<String, List<String>> groupedData = {};
  for (var teacher in rawTeachers) {
    String section = teacher['section'] as String;
    String name = teacher['name'] as String;
    
    groupedData.putIfAbsent(section, () => []);
    groupedData[section]!.add(name);
  }
  
  // 转换为Fields列表并更新状态
  setState(() {
    _sectionTeachers = groupedData.entries.map((entry) {
      return Fields(entry.key, entry.value);
    }).toList();
  });
}

3. ExpansionTile + ListView展示数据

在build方法中遍历分组后的列表,生成对应的展开项:

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(title: const Text('教师数据')),
    body: ListView.builder(
      itemCount: _sectionTeachers.length,
      itemBuilder: (context, index) {
        Fields currentSection = _sectionTeachers[index];
        return ExpansionTile(
          title: Text(currentSection.section),
          children: [
            ListView.builder(
              shrinkWrap: true,
              physics: const NeverScrollableScrollPhysics(),
              itemCount: currentSection.dataList.length,
              itemBuilder: (context, idx) {
                return ListTile(title: Text(currentSection.dataList[idx]));
              },
            )
          ],
        );
      },
    ),
  );
}

三、关键注意事项

  • 在initState中初始化调用_getData:
@override
void initState() {
  super.initState();
  _getData();
}
  • 内层ListView必须设置shrinkWrap: true和NeverScrollableScrollPhysics,避免嵌套滚动冲突
  • 若数据库数据量大,可考虑在DBHelper中直接执行分组查询(如SELECT section, GROUP_CONCAT(name) FROM teachers GROUP BY section),减少内存处理压力

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 18:25:02