ExoPlayer 已经是封装过的视频播映结构了,为什么还要封装一把,这样不是过度封装?其实不然,要是哪天ExoPlayer 不保护了或者有更好的播映器了,又或者是有些视频exo不能播映其他的播映器能够播映,又或者ExoPlayer 的api大改,要是不封装直接提供给事务用,那事务要改的当地就多了,所以封装一把是很有必要的。
如何去封装,并能提供给compsoe 或 View 运用?
咱们首要要来了解一下Exo 的根本运用。
ExoPlayer 的运用
ExoPlayer 大概的运用步骤和状况,如下。
- 初始化并获取播映器实例
咱们运用Hilt 依靠注入,来获取ExoPlayer 内核
运用Builder装备一下缓存和回调相关的东西,然后得到播映器实例
缓存相关的的注入如下,咱们暂时装备本地缓存的上限为 1g ,而且算法运用的是LRU
- 设置播映相关的参数、调用prepare办法
- 缓冲中
- 预备(能够播映)
- 播映中
- 暂停
- 中止,再次播映需求设置播映相关的参数并调用prepare办法
- 释放资源,需求构建新播映器才干播映
要获取ExoPlayer播映器相关的回调也很简单,只要设置一个Listener 就行了,如下
比方咱们要获取播映的位置来更新进度相关的,能够在onEvents 回调中处理。
ExoPlayer 运用就讲这么多,怎样去封装并提供给事务运用才是本文的重点。
封装播映器
视频播映会占用主进程许多资源,所以咱们还要把播映器相关的跨进程到子进程中去处理,这就涉及到跨进程通讯相关的了,在安卓中能够用来跨进程通讯的计划许多,比方LocalSocket,管道,EventFd,FIFO ,Binder 。Socket 基于流而且安全性较低而且运用都很费事,基于TCP的还有粘包问题。管道,FIFO,EventFd 这些都需求与文件打交道运用也很费事。从功能和安全运用上综合考虑,没有比binder 更适合播映器这种状况了,其实system_server进程把Surface 传递给app进程也是通过binder 来处理的。
界说两个接口,第一个用于播映器相关的,ExoPlayer播映器内核和咱们提供给事务方的播映器门面类都是完成这个接口的,另一个用于 Binder 跨进程通讯承继运用。
再界说两个AIDL接口,用于跨进程相关,一个用于播映控制,一个用于回调相关。
这些完成类咱们待会再说。咱们先来说下有限状况机。
播映器的整个流程用有限状况机FSM来控制,播映器初始化之后为 idle状况,release 为终究状况。
用事情来驱动整个状况机运行,并做出相应的操作。
比方预备事情,事务方通过调用prepare 办法并传递相关的参数,如在compose中运用
终究会在状况机内部履行,如下。
当然发送了事情也不能确保百分百就能切换到方针状况,比方咱们发送playEvent 有时候播映器内部出错了导致视频播映失败,此时也不可能把状况机置于playing状况。
必须要播映成功才干切换。
屡次发送同事情也能够进行过滤,当然状况机好处还不止这些。咱们再来看看跨进程相关的。
Binder 是CS架构,这里运用service来进行传递binder,主进程要衔接子进程,子进程要衔接主进程。
咱们界说两个Binder,用于衔接并进行跨进程通讯。
为什么IPlayerBinder 要承继IPlayer ?
由于这里咱们能够运用 kotlin by 关键字,将跨进程播映器的真实调用委托给binder 进行调用,能够少写一部分代理的模板代码。
主进程的服务如下
如何扩展其他播映器内核
要增加一个新的播映器内核,只要完成IPlayer就行了,并在EntryPoint入口点进行注入,如下伪代码。
界面相关
处理seek
完成弹幕作用,弹幕移动运用graphicsLayer的translationX 来处理 ,并运用layout把弹幕放到最右边
开端播映时,启动用于履行动画的协程
再聊一下Compose
最后还想再聊一下Compose, 其实Compose 已经能够用于任何界面了,无论从哪方面来和View比照,都是碾压 View 那一套UI系统的,并能无缝兼容View 那一套系统。
和Flutter 比照,运用上面其实没什么可比的,Flutter 和 Compsoe都是声明式的结构,都是一家人,都是Google的出品的(不得不说Google开源的结构都是精品,EXO也是Google的),可是Flutter写出来的界面体验绝比照不过Compose,别问我为什么,由于触摸事情要传递到Flutter 引擎这一层JNI 调用所发生的功能损耗怎样都解决不了,但Flutter 也不是不能用,有些不注重体验的事务完全能够运用Flutter来写。