使用AudioQuery开发Flutter音乐应用时ListView无法显示歌曲列表怎么办
问题原因&修复方案
核心问题1:缺少存储权限申请与校验
读取设备本地音频文件需要对应的存储权限,你当前代码未做任何权限处理,直接调用audioQuery.getSongs()会因为权限被系统拦截,返回空列表,此时songs.length=0,ListView自然无内容渲染。
核心问题2:无异常捕获与状态提示
你没有为异步查询逻辑增加异常捕获,也没有增加加载、空列表的兜底展示,即便查询失败或者设备无音频文件时,界面无任何提示,仅会显示空白区域。
其他潜在问题
非空安全模式下,如果albumArtwork返回空字符串而非null时,FileImage加载无效路径会抛出渲染异常,也可能导致列表渲染失败。
修复步骤
1. 配置平台权限
Android端
在android/app/src/main/AndroidManifest.xml中加入权限声明:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" /> <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" android:minSdkVersion="33" />
iOS端
在ios/Runner/Info.plist中加入权限说明:
<key>NSAppleMusicUsageDescription</key> <string>需要访问媒体库来读取本地音乐文件</string>
2. 引入权限处理依赖
在pubspec.yaml中引入以下依赖:
permission_handler:用于权限申请校验device_info_plus:用于判断Android系统版本适配不同权限规则
修正后完整代码
import 'package:flutter/material.dart'; import 'package:flutter_audio_query/flutter_audio_query.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:device_info_plus/device_info_plus.dart'; import 'dart:io'; class Tracks extends StatefulWidget { _TracksState createState() => _TracksState(); } class _TracksState extends State<Tracks> { final FlutterAudioQuery audioQuery = FlutterAudioQuery(); List<SongInfo> songs = []; bool isLoading = true; String? errorMsg; @override void initState() { super.initState(); checkPermissionAndGetTracks(); } Future<void> checkPermissionAndGetTracks() async { PermissionStatus status; if (Platform.isAndroid) { final androidInfo = await DeviceInfoPlugin().androidInfo; if (androidInfo.version.sdkInt >= 33) { status = await Permission.audio.request(); } else { status = await Permission.storage.request(); } } else if (Platform.isIOS) { status = await Permission.mediaLibrary.request(); } else { status = PermissionStatus.granted; } if (status.isGranted) { await getTracks(); } else { setState(() { isLoading = false; errorMsg = "请授予存储权限后使用"; }); } } Future<void> getTracks() async { try { songs = await audioQuery.getSongs(); setState(() { isLoading = false; }); } catch (e) { setState(() { isLoading = false; errorMsg = "读取音乐列表失败:${e.toString()}"; }); } } @override Widget build(context) { return Scaffold( appBar: AppBar( backgroundColor: Colors.white, leading: Icon(Icons.music_note, color: Colors.black), title: Text('Music App', style: TextStyle(color: Colors.black)), ), body: _buildBody(), ); } Widget _buildBody() { if (isLoading) { return const Center(child: CircularProgressIndicator()); } if (errorMsg != null) { return Center(child: Text(errorMsg!)); } if (songs.isEmpty) { return const Center(child: Text("设备中未找到音频文件")); } return ListView.separated( separatorBuilder: (context, index) => const Divider(), itemCount: songs.length, itemBuilder: (context, index) { SongInfo song = songs[index]; ImageProvider coverImage; if (song.albumArtwork != null && song.albumArtwork!.isNotEmpty) { try { coverImage = FileImage(File(song.albumArtwork!)); } catch (e) { coverImage = const AssetImage('assets/img.jpg'); } } else { coverImage = const AssetImage('assets/img.jpg'); } return ListTile( leading: CircleAvatar( backgroundImage: coverImage, ), title: Text(song.title ?? "未知歌曲"), subtitle: Text(song.artist ?? "未知艺术家"), onTap: () {}, ); }, ); } }
内容的提问来源于stack exchange,提问作者user16993309
相关产品推荐
相关产品推荐

