android绘制在哪个生命周期,Android MediaPlayer生命周期详解

关于Android播放器的生命周期,是我们在Android上开发视频播放的基础,必须熟练掌握。我们知道,Android官方给出了一张经典的生命周期状态图,如下图:

107038560_1

今天我们就根据这张图来详细聊聊MediaPlayer的生命周期。

音频/视频流生命周期回调和控制是通过如上图所示的状态机管理的。其中使用到了状态模式(一种设计模式,后续文章我们会详细讨论)。上图所示,MediaPlayer的生命周期回调是通过想逛播放操作时间控制的。椭圆圈展示了MediaPlayer可能处于的播放状态。箭头表示播放回调控制操作驱动MediaPlayer状态转换:单向箭头代表同步方法回调,而双向箭头代表异步方法回调。

而具体状态转化和操作如下:

MediaPlayer在new出来之后或者调用了reset()方法之后就进入了Idle状态,直到调用release()方法进入End状态结束。

107038560_2

在new出来之后和调用reset()方法之间有一点微小的差别,如果MediaPlayer仅仅只是new出来而没有调用reset()方法,播放器内部的播放引擎和对象的状态都还没有改变,如果此时调用getCurrentPosition()、getDuration()、getVideoHeight()、getVideoHeigh()、setVideoStreamType(int)、setLooping(boolean)、setVolume(float,float)、pause()、start()、stop()、seekTo(int)、prepare()和prepareAsync()方法都无法返回,因为框架无法回调客户端程序注册的OnErrorListener.OnError()方法,调用reset()方法之后,调用这些方法的错误信息就将被OnError()方法捕捉并返回。

MediaPlayer对象一旦确定不再使用就应该立即调用release()方法,释放与MediaPlayer对象关联的资源,以免占有硬件资源。导致之后创建的MediaPlayer对象无法使用资源。

107038560_3

MediaPlayer方法可以调用多个重载的setDataSource()方法从idle状态进入initialized状态。如果调用setDataSource()方法的时候,MediaPlayer对象不是出于idle状态,会报出IllegalStateException异常。SetDataSource()方法在调用的时候可能会发生IllegalArgumentException和IOException。

如果MediaPlayer是调用的自己的重载方法Create()传入资源文件的,那么此时MediaPlayer没有进入initialized状态,而是直接进入了prepared状态。

MediaPlayer可以调用prepared()方法和preparedAsync()方法进入prepared状态。调用prepared()方法直接进入parpared状态,调用preparedAsync()方法会进入preparing状态并返回,内部的播放引擎会继续完成未完成的工作。这两个方法可能发生IllegalStateException异常。

进入prepared状态后,会自动调用客户端程序注册的OnPreparedListener.OnPrepared()方法,可以在此方法里对MediaPlayer对象进行播放,及各种数据的获得,以及调整音量或者屏幕尺寸等操作。

在prepared状态下就可以调用start()方法进行播放了,此时进入started()状态,处于此状态下再次调用start()方法则没有影响。此状态下也会自动调用客户端注册的OnBufferingUpdateListener.OnBufferingUpdate()回调方法,对流播放缓冲的状态进行追踪。

107038560_4

pause()方法和start()方法是对应的,调用pause()方法会进入paused状态,调用start()方法继续播放。

stop()方法会使处于started、paused、prepared、playbackCompleted状态的MediaPlayer对象进入stoped状态,播放停止。

seekTo()方法可以调整播放的位置。seekTo方法是异步执行的,所以它可以马上返回。但是对于流媒体的播放,可能seekTo()方法会需要几秒钟的时间去完成。当seekTo完成时,会调用客户端注册的OnSeekCompleteListener.OnSeekComplete()回调方法。可以在此方法里做一些播放屏幕上的更新变化,比如发送隐藏控制界面的消息。

当资源播放完毕时,如果调用了setLooping(boolean)方法,会自动进入started状态重新播放,如果没有调用则会自动调用客户端播放器注册的OnCompletionListener.OnCompletion()方法,此时MediaPlayer对象进入playbackCompleted状态,在此状态里可以调用start()方法重新进入started状态。

107038560_5

播放View是继承SurfaceView的自定义View,继承SurfaceView后可以注册surfaceHolder的callback回调接口,实现其surfaceCreated()、surfaceChanged()及surfaceDestoryed()方法,surfaceCreated()方法在自定义播放View被创建的时候调用,surfaceChanged()方法在其改变的时候调用,surfaceDestoryed()方法在其销毁的时候调用。SurfaceHolder的生命周期是MediaPlayer在播放音频和视频时候的最大区别。通过SurfaceHolder的三个生命周期函数可以创建和释放某些资源。

Android内置的播放器并不是可以播放所有格式的视频文件,不能播放时videoHeight=0,videoWidth=0,以此来判断是否播放视频。

有的视频尺寸和播放View不一致时,可以重写OnMeasure(int,int)方法去调整视频播放时候的尺寸,以适应整个屏幕。其中在重写OnMeasure(int,int)方法时需要注意必须调用setMeasuredDimension(int,int)方法。

看完本文有收获?请分享给更多人

Java和Android架构

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值