遇到的问题是:播放下一个视频的时候,一直loading,研究了一下,使用下一个runloop解决
这里说一下视频播放的流程:
1. 获取视频地址URL
2. 根据URL获取视频缓冲
3. 当缓冲ok的时候,判断播放器state状态,当state == active的时候可以播放,stat = stop的时候不能播放。
下面从视频播放完成playToEnd开始说起:
/*视频播放完,开始下个视频播放*/
-(void)playToEnd {
state = active;/*播放器state需要是active的,如果是stop的情况就不播放下一个视频了。这里预设state是active*/
playNextVideo(state);
state = stop;/*由于playNextVideo用到了state,该行不能放到method之上*/
}
/*播放下一个视频*/
-(void) playNextVideo:(state ){
/*异步联网操作,获取视频url地址.前提是state = active*/
if(state == active){
[NetWrok connectNetwork:^{
startLoad();
}];
}
}
/*异步联网操作,根据地址获取一定缓冲*/
-(void) startLoad{
state = active;
startBuffer();
}
/*缓冲完成,开始播放画面*/
-(void) onBufferOK{
if(state = active){
play();
}
}
正常逻辑:
看调用playNextVideo(state)这一行(第4行),由于这个函数获取视频url地址是异步的,程序会先执行state=stop。然后网络应答后再调用startLoad,此时state=active;今儿onBufferOK函数,也能调用play函数了;
出问题逻辑:
[NetWrok connectNetwork^{}}在由缓冲的情况下,不发起实际的网络请求。立即应答,导致startLoad立即被调用。然而第5行执行state=stop了。最后即便onBufferOK调用,但是state还是stop状态,并么有调用play函数。程序state 死锁了。
解决办法就是:
在调用startLoad的那行加放到下一个runloop执行。保证playToEnd函数的第5行 state=stop先执行。代码如下:
/*播放下一个视频*/
-(void) playNextVideo:(state ){
/*异步联网操作,获取视频url地址.前提是state = active*/
if(state == active){
[NetWrok connectNetwork:^{
/*放到下一个runloop执行*/
dispatch_async(dispatch_get_main_queue(),^{
startLoad();
});
}];
}
}