- 使用wx.createInnerAudioContext()中onPlay等监听的奇怪问题观察和解决
问题描述: 在一个非首页的页面创建了一个全局的 mediaPlayer => wx.createInnerAudioContext() 在页面的onload 中设置了 onPlay 、onStop、onEnded、 三种监听方法。 业务逻辑:a. 在页面设置播放按钮,点击后用自定义方法playMusic 触发 mediaPlayer.play b. 离开页面时候,在onUnload中触发mediaPlayer.stop() 设置一个标记Index值 =》 初始 :0 ; 观察index在下列动作下的赋值: 播放按钮被点击:index => 0(赋值); 开始播放onPlay:先console.log(index), 再赋值 1 => index; 停止播放onStop:先console.log(index), 再赋值 2 => index 自然播放结束onEnded:先console.log(index), 再赋值 3 => index ; 代码如下: const mediaPlayer = wx.createInnerAudioContext() Page({ data: { index: 0, music: [ '这里放置你的音频文件链接' ] }, onLoad () { mediaPlayer.onPlay(() => { console.log('onPlay index:', this.data.index) this.setData({ index: 1 }) }) mediaPlayer.onStop(() => { console.log('onStop index:', this.data.index) mediaPlayer.src = '' this.setData({ index: 2 }) }) mediaPlayer.onEnded(() => { console.log('onEnd index:', this.data.index) mediaPlayer.src = '' this.setData({ index: 3 }) }) }, playMusic () { console.log('playMusic', this.data.index) this.setData({ index: 0 }) mediaPlayer.src = this.data.music[this.data.index] mediaPlayer.play() }, onUnload () { mediaPlayer.stop() } }) 实操试验: (三种方式) 第一种: 从一个面跳转到本页面,不做任何播放点击,直接返回上页,然后再进入本页,点击播放按钮直至播放自然结束 [图片] 从上图可以看到,三个监听都各执行了2次。 问题1:onStop在自然播放结束后,执行了两次。按照页面代码的业务逻辑,onStop是在离开页面后触发的,而我们这时候只离开过页面1次,就是在第一次进入后不做任何动作离开时会触发。为什么第二次进入后没有离开,点击播放完毕后,却触发了两次呢?? 问题2:onPlay 和 onEnd 被执行了两次,可以理解为,一次点击 和一次播放结束,触发了两次进入页面产生的onPlay 和 onEnd 。 问题3:需要注意的是 从上述例子可以看出,当我们离开页面的时候,wx.createInnerAudioContext() 创建的实例仍然是存在的,并没有被销毁。 问题4:那么我们在onUnload的时候,用mediaPlayer.destroy()进行销毁,会发生什么情况呢? 实际是,当你离开页面的时候销毁了播放实例,在再次进入(wx.navigateTo)该页面时候, 播放器已经不存在了,也就是说,触发一次wx.createInnerAudioContext() 的监听,只要触发一次,会一直存在,而为了避免这个情况,你如果在离开页面时用destroy去销毁,那么很抱歉,没有下一次了,因为对于被销毁的实例来说 destroy也是一直存在的,这看上去还真是逻辑很通畅呢。 第二种:从一个面跳转到本页面,点击播放按钮进行播放,在中途返回上一页,再进入本页,再点击播放,直到自然结束 [图片] 上图中我们可以看到, (1)红框内三次输出index是第一次进入后点击播放的操作结果。 index在这个过程中分别从0 => 1 =>2 .注意,index为2 是onStop也就是离开页面时候的赋值,上图的值均为赋值前的状态。 划重点: 在第一次播放离开后,index在离开这一刻,在onStop的触发下,被赋值为2。为什么这里要划重点呢?看下面你就知道诡异在哪里了。 (2)蓝框内是第二次进入页面后 点击播放,直到播放结束的index变化。按照代码逻辑,当我们点击按钮playMusic之后,index被赋值为0,然后再进行播放。而在onPlay的时候,我们是再一次输出index,按照正常逻辑,index此时应该是保持playMusic之后的状态0,但是你看到,在这里有两个onPlay,依次输出了2 和0两个不同的值。也就是说,this.data.index 在此刻有两个值。这是不是很诡异?我的理解是:其中那个2,是上一次离开页面的时候 onStop赋给index的那个2,这就回应了上面段落中的红色重点,但是如果你在页面的onload中输出this.data.index ,却永远是初始值0,你看不到那个2,那么这个2是怎么出来的,它究竟隐藏在哪里呢?这个需要腾讯的高科技人员来解读一下。 以上的监听疑惑,在业务上产生了各种麻烦(也许本人是理解不透),那么如何避免或者如何解决上面的问题呢? 我的办法是: 不要在页面全局设置播放组件,把播放组件的设置放到本页面的onload中,并把这个组件保存到本页面的data里面: onLoad () { this.setData({ mediaPlayer: wx.createInnerAudioContext() }) ..... 在使用该组件时,用this指向 如 this.data.mediaPlayer.play() 、 this.data.mediaPlayer.onEnd ... 如此,不存在多次监听和指向困惑。 我感觉,作用域,一直是小程序最大的一个没有能很好解决的问题,包括数据的双向绑定一直不能实现,也是属于作用域的实现方式。 总体来说,小程序框架距离一流的技术框架还相当遥远,使用小程序框架,有一种从六缸涡轮上下来换成4缸自然吸气的感觉。它一直存在很多问题,但却很少给程序员一种耳目一新的技术提升感
2021-04-01 - 关于shareTicket的bug
shareTicket 获取方式: 在 app.js 中通过 onShow(options) 中的options.shareTicket发现问题:当小程序入口为 群内点击,shareTicket 有值,但是从此转发任何页面到任何群(转发完毕后 app.js会自动被刷新),app.js 中的 onShow(options) 中 均存在shareTicket,包括转发给个人,也存在shareTicket, 而如果小程序入口为 非群内点击,app.js 中的 onShow(options) 是不存在shareTicket的,包括转发到个人或者群后,也不存在shareTicket。所以 只要入口为 群内点击,通过任何转发, shareTicket一直贮存在app.js 中的 onShow(options) 中,这个是一个bug吧?
2020-06-27 - backgroundaudiomanager 的音量问题
- 当前 Bug 的表现(可附上截图) backgroundaudiomanager 在播放mp3文件时候,音量会出现淡入淡出的效果,是否backgroundaudiomanager 接口默认的功能?- 预期表现 如果不需要这个功能 如何设置? - 复现路径 - 提供一个最简复现 Demo
2019-01-11