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

使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 08:15:04