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

如何在Flutter同一ListView中同时添加文本、音频两类JSON对象数据

Flutter 混合展示文本+音频列表实现方案

1. 封装统一数据结构&合并异步请求

因为需要同时拿到文本、音频两类数据才能做对应展示,首先用Future.wait并行请求两个接口,再把对应数据合并为统一的列表项模型:

// 首先定义列表项统一数据模型
class ListItem {
  final String contentText;
  final String audioUrl;
  // 可根据业务需求扩展章节号、经文序号等字段
  ListItem({required this.contentText, required this.audioUrl});
}

// 合并请求方法
Future<List<ListItem>> fetchCombinedData() async {
  // 并行发起两个请求,等待全部返回后再继续处理
  final responseList = await Future.wait([
    getText(),
    getAudio(),
  ]);
  final TextModel textData = responseList[0] as TextModel;
  final AudioModel audioData = responseList[1] as AudioModel;
  List<ListItem> resultList = [];

  // 按照顺序匹配对应文本和音频:该平台接口返回的经文顺序、数量完全一致,可直接按下标匹配
  // 注意:请根据你生成的实际模型层级,调整下面的字段取值路径
  for (int surahIndex = 0; surahIndex < textData.data.surahs.length; surahIndex++) {
    final textSurah = textData.data.surahs[surahIndex];
    final audioSurah = audioData.data.surahs[surahIndex];
    for (int ayahIndex = 0; ayahIndex < textSurah.ayahs.length; ayahIndex++) {
      resultList.add(ListItem(
        contentText: textSurah.ayahs[ayahIndex].text,
        audioUrl: audioSurah.ayahs[ayahIndex].audio,
      ));
    }
  }
  return resultList;
}

2. 替换原有FutureBuilder,渲染ListView

将原来仅请求文本数据的FutureBuilder替换为监听合并请求的实现,直接渲染每行的文本+音频播放控件:

// 首先在State类中声明合并请求的Future
late Future<List<ListItem>> combinedFuture;

@override
void initState() {
  super.initState();
  // 初始化时触发请求
  combinedFuture = fetchCombinedData();
}

@override
Widget build(BuildContext context) {
  return FutureBuilder<List<ListItem>>(
    future: combinedFuture,
    builder: (context, snapshot) {
      if (snapshot.hasData) {
        final itemList = snapshot.data!;
        return ListView.builder(
          itemCount: itemList.length,
          itemBuilder: (context, index) {
            final currentItem = itemList[index];
            return Padding(
              padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
              child: Row(
                children: [
                  // 展示对应文本
                  Expanded(child: Text(currentItem.contentText)),
                  // 音频播放按钮,可接入第三方音频库实现播放逻辑
                  IconButton(
                    icon: const Icon(Icons.play_circle, color: Colors.green),
                    onPressed: () {
                      // 此处实现播放currentItem.audioUrl的逻辑
                    },
                  )
                ],
              ),
            );
          },
        );
      } else if (snapshot.hasError) {
        return Center(child: Text('加载失败:${snapshot.error}'));
      }
      // 加载中展示动画
      return const Center(child: CircularProgressIndicator());
    },
  );
}

优化建议

  • 接口返回全量数据量级较大,建议增加分页加载逻辑,避免一次性加载全部数据导致页面卡顿
  • 若后续出现数据下标不匹配的情况,可通过经文的唯一编号做匹配,不要直接按下标取值
  • 音频播放逻辑可直接使用第三方音频库实现,无需自行封装原生能力

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 02:15:03