uni.createinneraudiocontext()是电台播放底层核心,但需结合uts单例状态管理、防抖校验的onended处理、跨端后台播放适配(如backgroundaudiomanager)及渲染优化才能实现全端一致的自动续播体验。

uni.createInnerAudioContext() 是实现电台播放列表交互的底层核心,但光靠它远远不够——网易云电台那种“自动续播、上下曲切换、进度同步、后台持续播放”的体验,本质是状态管理 + 事件驱动 + 跨页面通信的组合问题。
电台播放列表必须用模块级单例管理
很多同学直接在页面里 new Array() 存列表,结果切页后数据丢失、后台播放中断。正确做法是像 store/playlistStore.uts 那样用 UTS 模块级单例封装:
- 所有页面读写同一份
_playlist数组,不依赖 Vue 实例或页面生命周期 -
addToPlaylist()必须做sid去重,电台节目常有重复 ID(比如同一期重播) -
removeFromPlaylist()后要触发onEnded逻辑,否则当前播放项删了但音频还在播 - 不要用
vuex或pinia,它们在 App 端无法跨进程保活,UTS 单例才是真持久
innerAudioContext 的 onEnded 处理必须带防抖和索引校验
电台不是普通歌曲列表,onEnded 触发时不能无脑播下一首——可能用户刚手动切到上一首,也可能当前项已被移除。
- 每次
play()前先清空旧的onEnded监听器,避免事件叠加 - 在
onEnded回调里,用getIndexBySid()重新查当前项位置,再算下一首索引,而不是靠currentIndex++ - 加 100ms 防抖:iOS 上
onEnded可能连续触发两次,尤其在快速切歌后 - H5 端要额外监听
onTimeUpdate+duration判断是否真播完了,因为某些 MP3 文件末尾有静音帧,onEnded不触发
底部弹窗列表的 v-if 和 scroll-view 有渲染陷阱
网易云那种从底部滑出的电台列表,不是用 uni.showPopup 或第三方组件,而是纯 view + scroll-view,但容易卡顿或点击失效:
-
v-if控制显隐,别用v-show,否则 DOM 一直存在,iOS 下scroll-view滚动会掉帧 -
scroll-view必须设height(如60vh),且父容器加overflow: hidden,否则在 HarmonyOS 上滚动穿透到背景页 - 列表项绑定
@click="handleSelect(item)"时,确保item.sid是稳定值,别传index——电台节目翻页后index会错位 - 删除按钮用
catch:tap而不是@tap,防止滚动时误触发
App 端后台播放必须用 BackgroundAudioManager
innerAudioContext 在 App 端切后台就暂停,而电台需要持续播——这是最常被忽略的兼容点:
- 仅 Android/iOS App 需启用
uni.getBackgroundAudioManager(),H5 和小程序不用 - 初始化后立刻调用
manager.title = item.song和manager.epname = item.sing,否则锁屏界面不显示信息 - 所有播放控制(
play/pause/seek)必须同时操作innerAudioContext和manager,二者不同步会导致锁屏控件失灵 - App 端切前台时,检查
manager.playing状态,手动恢复innerAudioContext的currentTime
onEnded、H5 的静音帧、HarmonyOS 的滚动穿透、App 的后台降级——每个平台都在悄悄改写你对“播放结束”的定义。











