强迫症的研究——MediaPlayer播放进度条的优化

强迫症的研究——MediaPlayer播放进度条的优化

如何做一个优美、流畅而且准确的播放进度条,也许很多人觉得很简单,但实际上,这个问题在大部分时间都被忽略了。

计时方式的比较

  • 计时方式——主线程中使用Handler

    – 这种方式最简单,在主线程中通过handler.postDealyed(……, 1000),并在onHandleMessage中继续post消息,这样就实现了每隔1000ms进行一次消息循环。

  • 计时方式——使用单独计时线程

    – 单独创建一个计时线程,每秒发出time tick事件,主线程通过该事件来更新进度。这种方式比较麻烦,但是不麻烦怎么装逼呢?

    如何高雅、准确的实现

    对于Handler方式

  • 自身误差

这种方式下,如果使用handler.postDealyed(……, 1000)方式来进行每秒的计时,是不准确的,是的,有很大误差,误差的原因在于在你收到消息,到你重新发出handler.postDealyed的时间,并不是瞬间完成的,这里面有很多逻辑处理的时间,即使没有逻辑处理的时间,handler本身也是耗损性能的,所以消息并不可能按照理想的1000延迟来进行发送,这就导致了误差的累积。

  • 线程调度误差

我们知道,当音乐线程启动,到handler发出消息,这一段时间内,存在进程调度或者其它逻辑的耗时操作,导致这两个时间并不是同时发生的。所以,我们每次在post的时候,都需要对计时进行下补偿,但是,怎么做呢?

对于Handler方式的优化

我们知道,Android中有很多计时的控件,首先想到的是DigitalClock,结果发现已经废弃,好吧,看被什么替换了,OK,发现了TextClock,代码多了不少,感觉更牛逼了。我们直接看他是怎么处理这个问题的:

同样是通过程序员的嗅觉找到这里:

    private final Runnable mTicker = new Runnable() {
        public void run() {
            onTimeChanged();

            long now = SystemClock.uptimeMillis();
            long next = now + (1000 - now % 1000);

            getHandler().postAtTime(mTicker, next);
        }
    };

哎呦,有点意思,我们之前是通过postDelay来触发消息事件的,但这里系统使用了postAtTime,这是为什么呢?很自然我们会想到前面两行代码,其实也不用想太多,你代个值进去试下就知道了,假如now取出来是1200,那么next = 1200 + (1000 - 1200 % 1000)也就是next= 2000。你看,虽然我们前一次本该在1000触发的事件,被各种逻辑延迟到1200,那么如果你用postDelay,这个延迟就被累积了,但如果用这种方式,误差就被补偿了。

我们就叫他误差补偿算法吧~

对于单独计时线程方式

对于单独计时的线程,由于时间点的触发事件和主线程已经分开了,计时线程就不会受主线程逻辑的阻塞了,所以,只要保证开始时对起始时间差进行下同步就OK了。

对于单独计时线程方式的优化

其实对于单独计时线程来说,已经没有什么好优化的了,而且优点还能再列举不少:

  1. 计时逻辑与UI逻辑分离,方便拓展
  2. 计时准确,可以将计时线程封装,暴露接口,方便拓展
  3. 解耦、装逼

如果你还要再进一步优化的话,可以在计时的时候,使用时间差的方式来统计,虽然没什么乱用。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-12 14:21:20

强迫症的研究——MediaPlayer播放进度条的优化的相关文章

仿网易云音乐的播放进度条

仿网易云音乐的播放进度条,有三种状态:播放.暂停和拖动,只是实现了动画和主要的交互逻辑,其他细节(如暂停音乐的播放等)还需要自己完善: DKPlayerBar 是继承于UIControl的,如果想获取播放\暂停的事件建议用标准的addTarget方法: [playerBar addTarget:self action:@selector(playOrPause) forControlEvents:UIControlEventValueChanged]; 然后在DKPlayerBar里监听DKPl

VUE项目实现音乐播放器(四)------- 设计播放进度条 + 播放控制按钮

2020.3.31 9:18 好的,早上好各位,今天我们来进行一个很炫酷的页面开发——播放器控制页面( src\components\Play.vue ),如下图: 我们可以看到,该页面有很多元素组成,歌曲的封面.左上角的页面隐藏按钮,中间的播放进度条.歌词栏.下方的播放控制按钮.右下角的显示播放列表按钮,这些元素完美的结合在一起,整个页面有没有一种很高大上的感觉!好了,让我们来亲自动手实现它吧! 1. 歌曲封面&隐藏按钮 首先通过 getters 获取到歌曲的封面: computed: { i

Focusky教程 | 设置隐藏底部播放进度条

在播放演示文稿时,有些用户不大喜欢进度条显示在屏幕上,那么这里我们教大家如何在Focusky(也称为"FS软件")放映时显示或隐藏进度条. 1. 新建工程,编辑演示文稿,在菜单栏中找到"选项",如图1所示: [图1▲] 2. 点击"选项"按钮,然后选择"展示设置",找到"底部进度条设置",如图2所示: [图2▲] 3. 如果是想显示进度条,则勾选"显示底部进步条",不显示则不勾选该选项,

HTML5中的audio在react中的使用----语音播放进度条、倍速播放、下载等

最近做了一个将通话记录,语音转文字并可以在聊天记录里标注动机和摘要的需求,上图只是一个小小的模块,第一次接到使用到语音相关的需求,记录一下 上图是一个客服聊天记录的模块,语音转文字,将录音展示出来,可以音频播放,可以滑动进度条,倍速播放等等,以前自己心血来潮,使用原生js写过一个类似于网易音乐,播放音乐的播放器,包括进度条,音量调节啥的.当然做项目吗,还是使用HTML自带的更好,省时省力高高效我们的service后台前端工程使用的是react + ant-design + node作为中间层后端

html5 实现video标签的自定义播放进度条

现在随着html5的渐热,越来越多的web开发者都开始选择使用html5写出一些比较好的web应用. html代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>HTML5-Video-Player</title> <style type="text/css"> .vi

基于Jquery的音乐播放器进度条插件

自己基于豆瓣FM的ui仿写qq音乐时,基于Jquery手写的进度条插件,效果图如下: 主要特色: ① 可自适应挂载元素的宽度,也可以自己设置进度条宽度: ② 支持部分默认参数修改(具体见使用说明): ③ 允许最大时间为23:59:59,高于此值将默认修改为此值: ④ 可以自己控制进度条动画的开关及重置: ⑤ 可以获取进度条当前时间和宽度,与H5的audio标签协调使用. 使用说明: /* * 功能描述:播放器进度条 * 参数: * option:挂载父元素 * inTime:进度条时间长度 *

视频控制的简易进度条

视频控制的简易进度条 样式: 作用:控制视频的播放点,实时显示视频播放位置 html: <div class="coll"> <span name="progress"> <b></b> <b></b> <b></b> </span> </div> css: .coll{position: absolute;bottom: 20px;left: 2

EasyUI添加进度条

EasyUI添加进度条 添加进度条重点只有一个,如何合理安排进度刷新与异步调用逻辑,假如我们在javascript代码中通过ajax或者第三方框架dwr等对远程服务进行异步调用,实现进度条就需要做到以下三点: 在异步刷新之前打开进度条 异步刷新的过程中不断的刷新进度数据 异步刷新之后关闭进度条 详细代码 代码如下所示: <div id="a" class="easyui-dialog" title="进度" data-options=&qu

Android MediaPlayer播放音乐并实现进度条

提前工作,往sd卡里放音乐文件 1.布局文件main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="