谈一个项目中的架构吧,在我们的项目中,视频播放是一个非常重要的模块,其业务形态也是多种多样的,而且业务形态变动频次也非常的高,当前版本是A方式,下一个版本就可能变为B方式,如何才能适应该情况的,我们需要一个兼具弹性、可读、可维护、易扩展、稳定的框架。
先说一下该框架之前的开发模式:
在我们的项目中的,涉及播放的包括:列表流式播放、详情页播放、小窗播放、全屏播放(分两种:横屏全屏和竖屏全屏),可能的触发播放的方式包括:点击播放,滑动播放,拉起详情页后自动播放,由半屏播放点击全屏按钮切为全屏播放,直接打开全屏播放。为实现前面所述业务形态,在项目前期采用的方式是具体业务具体实现,抽取通用的视频播放模块。结构图如下所示:
其缺点是相当明显的:
a.除播控及VideoView外,其他的播放逻辑均分散在各业务模块中,代码冗余度高,代码差异大
b.业务分散导致与播放相关的逻辑业务开发人员均需理解并掌握播放逻辑,增加了开发成本及维护成本
c.业务逻辑耦合度高,导致新业务加入困难,意味着项目的扩展性差
d.bug数量一样居高不下,稳定性差
因此,抽象通用的播放框架迫在眉睫。
方案包括以下几项:
1.提取多种播放形态:
(1)列表流式播放--横屏
(2)列表流式播放--竖屏
(3)竖屏全屏播放
(4)横屏全屏播放
(5)半屏播放下部带信息
2.提取三个控件类,结构如下所示:
(1)VideoPlayWrapView的作用为:
a.提供可以接受各业务的统一容器,消化不同的业务决定子Fragment呈现的具体外在形态,可能不太好理解,举个例子:接受到的业务要求为列表流式播放,则VideoFragment的呈现形式为半屏,下部的VideoDetailContainerFragment为隐藏状态。
b.对外封装统一的事件响应,对内区分分发的子View
c.统一封装各业务的回调,发往外部
(2)与播放相关的封装位于VideoFragment,其功能包括以下几条:
a.盛放播放控件VideoView及播控
b.与播放器相关的逻辑(开启、关闭、暂停等)
c.响应外部条件变化对播放的影响(如网络、电池等)
d.播控上提供的功能
(3)VideoDetailContainerFragment是一个插件,该处可以替换为别的模块,由业务方决定,在播放窗的下方放置什么业务模块。
3.提取统一的业务处理功能,包括以下几类:
a.播放
b.暂停
c.停止
d.VideoDetailContainerFragment展开(动态效果)
e.VideoDetailContainerFragment显示
f.VideoDetailContainerFragment隐藏
g.其他业务支持(如系统权限相关)
上述的业务处理功能统一使用常量命名,业务方只需负责发送业务分类。在统一的播放模块中不区分来源,只区分业务本身,取不同的处理方式,实现了业务与处理的分层隔离
4.统一规划与手势相关(点击、滑动)的事件分发逻辑,上层的Fragment、Activity负责接受事件,然后传递给VideoPlayWrapView,由VideoPlayWrapView决定分发给那个子布局处理
5.权限处理逻辑提供基本功能,是否触发由上层业务决定
最终的框架图为: