拆解需求 1. RN使用 2. 播放器
最终实现的播放器功能:可以提供给RN使用,不带边缓存边播放功能的播放器。
1. RN使用实现
以组件的形式提供给RN使用,至于组件和native如何交互,主要通过重写RN的ViewGroupManager<T>实现。泛型传入的就是RN组件包装的native内部实现的播放器的view(player view)。
RN组件向native通信:
重写receiveCommand方法,此方法带有参数palyer view,commandId(RN到native的映射关系通过重写getCommandsMap建立)args(携带数据)。
拿到player view实例,我们就可以根据具体的命令,调用实例里面的方法。如此就实现的RN调用native。
Native向RN通信:
主要是native的view与用户发生交互,需要通知到RN。通知的实现是EventDispatcher,如何拿到player view并监听player view里面的事件呢?在createViewInstance方法里面可以拿到player view,在view里面设置监听,回调方法中利用EventDispatcher通信RN。
RN如何向Native传入初始化信息呢?比如控件的宽高。通过@ReactProp 注解的方式。
2. 简单播放器的实现
使用源生MediaPlyaer实现的视频播放,不带有边下边播功能(如果是网络视频,会出现缓冲很久的情况)。
推荐封装一个自己的MediaPlyaer,比如起名SelfMediaPlayer。以View的形式对外提供使用(内部聚合了SelfMediaPlayer)。
实现时,我们有些需要注意的地方有: 1. MediaPlayer状态的管理 2. 注意收集mediaplayer上报信息并进行处理。3. 无论选择SurfaceView还是TextureView,最好用一个FrameLayout包裹它。
MediaPlayer状态的管理:
以实现对外提供的api start功能实现来说明。
@Override
public void start() {
try{
mediaPlayer.start();
} catch(IllegalStateException e) {
// invalid state
// 这里可以加入自己的处理逻辑,建议定个listener交给使用者确定ivalid错误处理逻辑。
}
}
收集mediaplayer上报信息并进行处理:
mediaplayer通过一系列listener上报播放时的相关状态信息。比如OnErrorListener监听mediaplayer进入Error状,OnPreparedListener监听mediaplayer进入Prepared状态。
MediaPlayer.OnErrorListener errorListener = new MediaPlayer.OnErrorListener() {
public boolean onError(MediaPlayer mp, int framework_err, int impl_err) {
// The MediaPlayer has moved to the Error state, must be reset!
// 代表进入错误状态了,我们可以进行自己错误处理逻辑并同时给出interface让使用者监听
// 这里,我们也可以记录下状态,因为error这个状态很特殊,在进入到如此状态后后续很多操作都不可用了,必须reset。
return true;
}
}
private MediaPlayer.OnPreparedListener mPreparedListener = new MediaPlayer.OnPreparedListener
() {
@Override
public void onPrepared(MediaPlayer mp) {
// 这里可以记录下prepared状态,因为很多操作的前提就是当前状态是prepared
}
};
无论选择SurfaceView还是TextureView,最好用一个FrameLayout包裹它
带来的优点有很多,可以通过控制framelayout的大小实现间接控制SurfaceView大小。有了父容器的包裹之后,我们可以扩展一些定制化的view。