Android播放器设计随笔

工作之中写过两个播放器,大同小异,由于需要的功能不是太多,github上的功能都比较多,正好想着顺手练练技术,于是手撸过两个播放器。播放器这个东西吧,说难不难,因为播放内核基本都是用的ijk,自己写其实就是在把UI和功能做个封装,说简单吧,也没那么简单。主要是功能太多了,经常写着写着就写乱了。每次写都是写之前胸有成竹,然后越写脑子越乱。通过这次写播放器的过程,简单记录一下为什么会产生这种问题,以及怎么解决方式,还有播放器设计的一些经验。

API设计

其实就一句话,功能繁多,难以界定。

咱们先说基础播放View,基础播放View一般是由三个部分组成:播放器内核(IPlayer),渲染层(IRender),跟布局(ViewRoot,也就是封装起来BasePlayView)。由于播放器内核、渲染层的实现都有很多种,所以我们一般来说是把这两个模块各自抽象一个接口或者抽象类出来,下边的文章就用他们的接口名称代指。现在持有一个IPlayer和IRender的ViewGroup(一般是FrameLayout)将会封装成一个包含基础播放能力,但是没有控制层Ui的BasePlayView。
在这一步中,最容易引起设计混乱的原因就是功能的模块划分。
其中BasePlayView是最终对应用层暴露出api的对象,BasePlayView中80%的功能是由Player接口提供的,10%的功能是由Render接口提供的,10%的功能是自己实现的如全屏, 小屏播放。
IPlayer的功能基本是由播放器内核提供的,这就造成了一套繁琐的功能转发逻辑,最终暴露的功能——>IPlayer——>播放器内核 。之前都是先设计播放器的接口 在设计Render 然后最后写BasePlayView。其实这样的顺序是错误的,我们应该先设计最终对外暴露的接口,在设计内部接口,有外到里,这样就会大大减少后期出现设计不合理,功能短缺的问题,这个顺序相当于先设计需求,在设计实现。我之前用的顺序是先设计实现,在反推需求。很容易造成发现需求短缺 在重新设计接口。这样很容易打乱原有的设计思路,导致初期设计合理的框架 为了实现某个需求不得不重新设计/生插进去一个功能。前者浪费时间,需要从新缕思路,会忘记之前的思路, 后者可能短期内不会暴露问题,但是会埋雷,必经是不符合前期设计的东西。初期功能尽量设计全 否则后期改动真的太麻烦了。还有就是功能的界定,需不需要我在最基础的base层去实现,base功能定义是最基本的播放相关功能吗,有哪些复杂功能需要分层设计,以及分层设计的思路,用继承分层,还是利用多层View分层。哪些功能定义在控制器 哪些功能定义在播放器实现。这些都是功能划分上的难点。这些没有统一的定论,但是必须要有统一规范。

还有释放的管理,由于设计到多个模块释放,需要规定哪些部分是由应用调用释放的,哪些是内部根据自己处理的。

状态管理

还是上边的三个模块,播放器的状态是由这三个模块共同产生的,不规划好管理职责也会导致后期的代码逻辑混乱

  • 状态必须由一个set api统一管理,这是最重要的
  • 状态集的定义基础播放状态,播放器功能状态 等等提前定义 我需要管理多少状态,其他状态我是交由下层管理,还是通过回调事件分发出去。
  • 是否允许叠加状态,单状态能满足大部分情况,但是极少部分情况需要一个叠加状态,比如播放器 全屏 小屏 普通厅 | 播放 暂停 等待 等等...
  • 最好BasePlayView做状态管理, Player 和Render 自身状态通过回调通知BasePlayView
  • 设计方便下层view 扩展状态管理的逻辑

状态切换的switch语句

状态切换也是比较麻烦的一个事情,需要做大量的判断,比如仅仅是一个start操作,就得根据是一个空闲播放器、正在播放中、暂停、播放完成、播放错误这五个状态做不通的操作。这还没考虑网络状态,是否在后台等。

所以如果根据状态的操作,以及操作产生的状态切换这一快非常容易产生大量的switch或者if代码。如果在这里代码逻辑过于混乱,后期会引起很多难以控制的问题。我的在处理这个问题的时候用了一种类似状态机的设计理念,但是并不是标准的状态机。大致思路就是生成一个BaseState类,api是BasePlayView所有可能触发的操作。比如 播放、暂停、发生错误、断网、播放完成等。播放器持有一个BaseState对量,每当播放器切换一个状态,都会切换BaseState具体的子类,然后将每当播放器接受到一个事件,则将事件转发到当前BaseState去实现具体操作。因为此时的BaseState 对象中是知道自己是处于什么状态的,也就避免了大量的逻辑判断操作。

功能分层的设计

现在一个完善的播放器的功能种类繁多,在一个或者几个类中完成所有功能代码是不显示,必须分层设计,我之前写的播放器的功能分成是用继承实现的,最基础的播放器——>带进度条——>手势控制——>支持无缝衔接

不同功能的播放器 只能通过继承合适层级的播放器 然后再去添加自己的代码实现。扩展性很差,其他不熟悉内部实现的同事用起来很难受,只能用我封装好的。

通过看DK播放器的实现,他使用组合控制器实现的功能分层。用一个没有UI的根控制器做容器,跟控制器负责所有控制器的统一性功能,以及转发播放器状态变化。上述的功能实现就可以改成基础功能播放器——>支持无缝衔接(这是播放器强相关功能,只能继承实现)+进度条控制器+手势控制器。耦合性更低 。通过组合不同的控制器就可实现不同的播放器。

如果把和播放器强相关的功能也用上诉组合的形式 分层实现 我现在的思路是 把所有的api调用改为命令模式,可以自定义命令处理器,链式调用 完成功能拦截,或者功能增强,自定义拦截器级别,类似Okhttp 拦截器设计。

管理模块

这个角色基本上就是管理全局的播放器实例对象,或者提供几个产生播放器实例的工厂方法。一般全局性的播放设置也放在这里。这里最容易发生的问题就是全局设置功能和播放器的设置API的设置冲突,原则是以播放器的设置为主。然后就是播放器的设置api必须包含全局的设置项,也就是假如全局可以设置ABC三个属性,那么播放器的设置API最少要包含ABC三个设置API。当然如果设置不是针对个体播放器的可以不用满足上述条件。

这篇文章基本就是个随笔,想到哪写到哪。记录了下写一个播放器想到的东西,给以后做功能设计留一些参考资料,不写出来估计过几天就忘了,年纪大了记性实在不行了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343