现在的位置: 首页 > 综合 > 正文

Intent传递extra data,小心坑!

2017年08月04日 ⁄ 综合 ⁄ 共 1753字 ⁄ 字号 评论关闭

    今天在测试之前写好的一个功能模块时发现了一个关于Intent的使用、算是比较隐蔽的坑,后面经过一番折腾后找到问题所在。


上下文环境:

    我们的项目是DTV player,里面有个播放模块。播放分live tv和remote file,这里就拿live tv说事。play live可以分为主动选择channel播放和软件自动恢复播放。主动选择channel播放,是指用户在channel list界面(一个显示所有channel的Activity)点击一个channel播放。软件自动恢复播放,是指player启动或者事件(来电、锁屏等)中断后自动播放最后一次播放的channel。从spec的角度来说,事件中断后的恢复播放是只播放,而不主动跳转到播放界面(保持事件中断之前的界面);其他的播放行为(主动选择播放、player启动恢复播放)除了播放还要跳转到播放界面。


    针对这个spec,大概的播放流程是这样设计的。在一个公共类中设计了一个autoPlay方法,上面提到的所有自动恢复播放都由这个方法处理,这个方法的最后会得到将要播放的相关参数(playType和index)。不需要跳转到播放界面的播放行为在autoPlay方法最后相应位置直接调用play方法播放。需要跳转到播放界面的播放行为(主动选择播放、player启动恢复播放),统统由发起播放请求的位置将播放需要的参数包装到Bundle对象里,然后通过Intent传递给播放界面。在播放界面通过Intent获取这个extra
data,然后执行播放。

    发现问题后再回想这段逻辑的设计,其实是有问题的。


测试操作:

    从channel list里面选择一个channel,点击播放(这时跳转到播放界面)。在播放界面通过手势换台(使得当前播放的channel与刚点击播放的channel不一样),按电源键使设备休眠,再按电源键使设备恢复,解锁。按照spec,这时候会在autoPlay方法中直接调用play方法恢复上一次的channel播放。 

问题:

    每次恢复播放的channel都是最开始点击channel list播放对应的channel,而不是事件中断之前正在播放的channel。(好吧,之前那么多轮测试居然没发现这个问题)

    经过一番折腾,一项项排除后发现是播放界面接收处理Intent的extra data的地方有问题。


    上面的测试case中,最后恢复播放是在autoPlay方法里面调用的。由于事件中断之前是在播放界面,所以这时候的播放界面是由系统恢复的。界面恢复时程序执行到了上面提到的接收处理Intent的extra data的地方。这个时候getIntent方法返回值不为null,通过返回的这个intent能获取到extra data(之前这块的代码判断条件是,能获取到相应的extra data,则执行播放,否则什么也不做)。这个extra data就是最后一次在channel
list界面点击channel播放传递过来的extra data,所以就恢复播放了最后一次点击channel list的channel。

    一般情况下,后一次通过Intent传递的参数会覆盖前一次传递的参数(前提是这两次传参的类型一样,并且map的key一样),所以在此之前的工作经验中,所有使用Intent传参的地方都没遇到过问题(真是够侥幸)。但是在上面的场景中就一定会遇到问题。那么为了解决这个问题,需要在取出Intent的extra data之后,调用Intent对象的removeExtra方法将之前的extra data释放掉


    到此,问题解决。但是在解决掉这个问题之后,反过来回想整个播放流程的设计好像也是欠妥。有两个地方执行播放行为,一是不跳转界面时在autoPlay方法中,二是跳转界面后在VideoPlayer类(上面提到的播放界面)中执行播放行为。一个是直接调用play方法执行播放,另一个是通过Intent传参给VideoPlayer执行播放。都是播放行为,这里用了两种方式。为了改进这个设计,需要为播放再封装一层,对上下都屏蔽这两种行为的不统一。把真正的播放行为抽出来,使其行为在任何时候都统一,不依赖于是否有界面跳转。

   

抱歉!评论已关闭.