问题描述:
- 在一个非首页的页面创建了一个全局的 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缸自然吸气的感觉。它一直存在很多问题,但却很少给程序员一种耳目一新的技术提升感