android texturevideoview 缓存,TextureView实现VideoView

传统的VideoView基于SurfaceView实现,适用于不需要考虑布局的场景。然而在可滑动布局如ListView中,SurfaceView会带来延迟问题。本文介绍如何通过TextureView重写VideoView,解决延时问题。首先分析VideoView源码,然后逐步替换SurfaceView相关代码,添加对TextureView的初始化和尺寸变化的支持,最后实现关键功能,如播放、暂停、尺寸调整等。
摘要由CSDN通过智能技术生成

传统的VideoView是基于SurfaceView实现的,SurfaceView是在屏幕上指定区域新加的一个绘制区域,不在layout布局上,不受布局限制,绘制效率高,但在ListView等可滑动布局中使用时,会有一定的延时黑影,快速拖动时、低端机上出现的很明显。为解决这个问题,下面基于TextureView重写VideoView--TextureVideoView。

1.查看VideoView源码,发现它是直接继承于SurfaceView,实现MediaPlayerControl接口的,所以我们类似的实现它。好,现在的代码长这样子。

/**

* 基于texture的播放器。可放在listview的item中

*

* Created by cailingxiao on 2017/9/26.

*/

public class TextureVideoView extends TextureView implements MediaController.MediaPlayerControl {

public TextureVideoView(Context context) {

super(context);

}

public TextureVideoView(Context context, AttributeSet attrs) {

super(context, attrs);

}

public TextureVideoView(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

}

@Override

public void start() {

}

@Override

public void pause() {

}

@Override

public int getDuration() {

return 0;

}

@Override

public int getCurrentPosition() {

return 0;

}

@Override

public void seekTo(int pos) {

}

@Override

public boolean isPlaying() {

return false;

}

@Override

public int getBufferPercentage() {

return 0;

}

@Override

public boolean canPause() {

return false;

}

@Override

public boolean canSeekBackward() {

return false;

}

@Override

public boolean canSeekForward() {

return false;

}

@Override

public int getAudioSessionId() {

return 0;

}

}

2.复制下VideoView通用逻辑。调整下面几个地方:

2.1 将SurfaceView相关的地方删除;

2.2 将subtitle相关的东西删除;

2.3 在init中加入对TextureView的初始化,添加监听SurfaceTextureListener并实现;

2.4 增加对尺寸变动的支持,之前surfaceView里面有setFixedSize方法来修改大小,所以我们也需要实现个;

最终代码:

public class TextureVideoView extends TextureView implements MediaController.MediaPlayerControl {

private static final String TAG = "VideoView";

// all possible internal states

private static final int STATE_ERROR = -1;

private static final int STATE_IDLE = 0;

private static final int STATE_PREPARING = 1;

private static final int STATE_PREPARED = 2;

private static final int STATE_PLAYING = 3;

private static final int STATE_PAUSED = 4;

private static final int STATE_PLAYBACK_COMPLETED = 5;

// settable by the client

private Uri mUri;

private Map mHeaders;

// mCurrentState is a VideoView object's current state.

// mTargetState is the state that a method caller intends to reach.

// For instance, regardless the VideoView object's current state,

// calling pause() intends to bring the object to a target state

// of STATE_PAUSED.

private int mCurrentState = STATE_IDLE;

private int mTargetState = STATE_IDLE;

// All the stuff we need for playing and showing a video

private MediaPlayer mMediaPlayer = null;

private int mAudioSession;

private int mVideoWidth;

private int mVideoHeight;

private int mSurfaceWidth;

private int mSurfaceHeight;

private MediaController mMediaController;

private MediaPlayer.OnCompletionListener mOnCompletionListener;

private MediaPlayer.OnPreparedListener mOnPreparedListener;

private int mCurrentBufferPercentage;

private MediaPlayer.OnErrorListener mOnErrorListener;

private MediaPlayer.OnInfoListener mOnInfoListener;

private int mSeekWhenPrepared; // recording the seek position while preparing

private boolean mCanPause;

private boolean mCanSeekBack;

private boolean mCanSeekForward;

private Context mContext;

private SurfaceTexture mSurfaceTexture;

public TextureVideoView(Context context) {

this(context, null);

}

public TextureVideoView(Context context, AttributeSet attrs) {

this(context, attrs, 0);

}

public TextureVideoView(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

init();

}

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)

public TextureVideoView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {

super(context, attrs, defStyleAttr, defStyleRes);

init();

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

//Log.i("@@@@", "onMeasure(" + MeasureSpec.toString(widthMeasureSpec) + ", "

// + MeasureSpec.toString(heightMeasureSpec) + ")");

int width = getDefaultSize(mVideoWidth, widthMeasureSpec);

int height = getDefaultSize(mVideoHeight, heightMeasureSpec);

if (mVideoWidth > 0 &

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值