--- description: 音乐播放器开发模式与最佳实践 globs: ["**/view/**/*.ets", "**/viewmodel/**/*.ets", "**/controller/**/*.ets"] alwaysApply: false --- # 音乐播放器开发模式与最佳实践 ## 播放状态管理 ### 播放状态枚举 使用 `PlayStatus` 枚举管理播放状态: ```typescript import { PlayStatus } from '../common/PlayStatus'; // 在组件中使用 @State playStatus: PlayStatus = PlayStatus.INIT; ``` ### 状态转换模式 ```typescript // 播放/暂停切换 togglePlay() { if (this.playStatus === PlayStatus.PLAY) { this.pauseMusic(); this.playStatus = PlayStatus.PAUSE; } else { this.playMusic(); this.playStatus = PlayStatus.PLAY; } } ``` ## 音频会话管理 ### AvSessionController使用 ```typescript import { AvSessionController } from '../controller/AvSessionController'; // 获取控制器实例 private avSessionController = AvSessionController.getInstance(); // 在页面生命周期中注册/注销 aboutToAppear() { this.avSessionController.registerSessionListener(); } aboutToDisappear() { this.avSessionController.unregisterSessionListener(); } ``` ## 歌词处理模式 ### 歌词解析与显示 ```typescript // 使用lib中的LyricHelper import { LyricHelper } from '@lib/LyricHelper'; // 解析歌词文件 LyricHelper.parseLyricFile(lyricPath) .then(lyrics => { this.lyrics = lyrics; }) .catch((err: Error) => { Logger.error(`歌词解析失败: ${err.message}`); }); ``` ### 歌词同步显示 ```typescript // 根据当前播放时间获取对应歌词行 getCurrentLyricLine(currentTime: number): LyricLine | null { if (!this.lyrics || this.lyrics.length === 0) { return null; } for (let i = 0; i < this.lyrics.length; i++) { if (this.lyrics[i].time > currentTime) { return i > 0 ? this.lyrics[i - 1] : null; } } return this.lyrics[this.lyrics.length - 1]; } ``` ## 媒体文件处理 ### 支持的音频格式 使用 `CommonConstants.REAL_MUSIC_FORMAT` 检查文件格式: ```typescript import { CommonConstants } from '../common/constants/CommonConstants'; function isMusicFile(fileName: string): boolean { const ext = fileName.substring(fileName.lastIndexOf('.')).toLowerCase(); return CommonConstants.REAL_MUSIC_FORMAT.includes(ext); } ``` ### 媒体扫描与索引 ```typescript // 扫描本地音乐文件 async scanLocalMusic(): Promise { const musicFiles: MusicItem[] = []; const context = getContext(this); // 使用文件系统API扫描 // 实现细节取决于具体需求 return musicFiles; } ``` ## 播放列表管理 ### 播放列表模型 ```typescript import { Playlist } from '../viewmodel/Playlist'; // 创建播放列表 const playlist = new Playlist(); playlist.name = "我的播放列表"; playlist.songs = [song1, song2, song3]; // 保存到本地存储 PreferencesUtil.saveObject('playlist_' + playlist.id, playlist); ``` ### 播放模式 ```typescript // 播放模式枚举 enum PlayMode { SEQUENCE, // 顺序播放 LOOP, // 循环播放 RANDOM, // 随机播放 SINGLE // 单曲循环 } // 切换播放模式 switchPlayMode() { const modes = Object.values(PlayMode); const currentIndex = modes.indexOf(this.playMode); this.playMode = modes[(currentIndex + 1) % modes.length]; } ``` ## 主题适配 ### 主题切换 ```typescript import { myTheme } from '../common/AppTheme'; // 在组件中使用主题颜色 @Builder PlayerControl() { Row() { Button('播放') .backgroundColor($r('app.color.brand')) .fontColor($r('app.color.fontOnPrimary')) } .backgroundColor($r('app.color.backgroundPrimary')) } ``` ### 动态主题更新 ```typescript // 更新主题 updateTheme(themeIndex: number) { const themeList = [DefaultTheme, TwilightTheme, ForestTheme, CoralTheme, MidnightTheme]; AppStorage.SetOrCreate('themeColor', themeList[themeIndex].colors.brand); } ``` ## 性能优化 ### 图片加载优化 ```typescript // 使用缓存和懒加载 Image(this.coverUrl) .width(50) .height(50) .borderRadius(8) .objectFit(ImageFit.Cover) .alt($r('app.media.default_music_icon')) .onComplete(() => { // 加载完成回调 }) .onError(() => { // 加载失败回调 }) ``` ### 列表性能优化 ```typescript // 使用LazyForEach和缓存 LazyForEach(this.musicData, (item: MusicItem, index: number) => { ListItem() { MusicItemComponent({ musicItem: item }) } }, (item: MusicItem) => item.id.toString()) ``` ## 错误处理 ### 播放错误处理 ```typescript // 播放错误处理 handlePlaybackError(error: Error) { Logger.error(`播放错误: ${error.message}`); this.playStatus = PlayStatus.INIT; // 显示错误提示 ToastUtil.showToast(`播放失败: ${error.message}`); } ``` ### 网络请求错误处理 ```typescript // API请求错误处理 fetchLyrics(title: string, artist: string) { const url = `${CommonConstants.LRC_API}?title=${encodeURIComponent(title)}&artist=${encodeURIComponent(artist)}`; fetch(url) .then(response => { if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } return response.json(); }) .then(data => { this.processLyrics(data); }) .catch((err: Error) => { Logger.error(`获取歌词失败: ${err.message}`); // 使用备用API或显示错误 }); } ```