最近在写一个和视频有关的项目,遇到了这个问题,开始使用ListView中嵌入MediaPlayer和TextureView老是出问题,播放的时候item会出现错乱的现象,原因在于使用ViewHolder复用View导致的,如果每次都重新加载View就不会出问题了,这个demo中没有使用ListView,使用了android.support.v7.widget.RecyclerView,达到了预期的目的,希望对正在迷茫中的你有所帮助。
在一个列表视频交流群( 290087364)中找到了一个Demo,然后在此基础上进行了修改,感谢群主的无私贡献,我也不能太自私了,就贴出来,希望能抛砖引玉,给大家带来一点的帮助。
首先看一下,重写的一个TextureView,代码中没有注释,代码量比较少,很容易理解,TextureVideoView主要用于控制视频的播放。
package com.example.textureviewdemo;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.SurfaceTexture;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnBufferingUpdateListener;
import android.media.MediaPlayer.OnInfoListener;
import android.util.AttributeSet;
import android.view.Surface;
import android.view.TextureView;
import android.view.TextureView.SurfaceTextureListener;
@SuppressLint("NewApi")
public class TextureVideoView extends TextureView implements SurfaceTextureListener {
private MediaPlayer mediaPlayer;
private Context context;
MediaState mediaState;
public MediaPlayer getMediaPlayer() {
return mediaPlayer;
}
public interface OnStateChangeListener{
public void onSurfaceTextureDestroyed(SurfaceTexture surface);
public void onBuffering();
public void onPlaying();
public void onSeek(int max,int progress);
public void onStop();
}
OnStateChangeListener onStateChangeListener;
public void setOnStateChangeListener(OnStateChangeListener onStateChangeListener) {
this.onStateChangeListener = onStateChangeListener;
}
//监听视频的缓冲状态
private OnInfoListener onInfoListener=new OnInfoListener() {
@Override
public boolean onInfo(MediaPlayer mp, int what, int extra) {
if(onStateChangeListener!=null)
{
onStateChangeListener.onPlaying();
if(what==MediaPlayer.MEDIA_INFO_BUFFERING_START)
{
onStateChangeListener.onBuffering();
}else if (what == MediaPlayer.MEDIA_INFO_BUFFERING_END) {
onStateChangeListener.onPlaying();
}
}
return false;
}
};
//视频缓冲进度更新
private OnBufferingUpdateListener bufferingUpdateListener=new OnBufferingUpdateListener() {
@Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
if(onStateChangeListener!=null)
{
if(mediaState==MediaState.PLAYING)
{
onStateChangeListener.onSeek(mediaPlayer.getDuration(), mediaPlayer.getCurrentPosition());
}
}
}
};
public TextureVideoView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
init();
}
public void init() {
setSurfaceTextureListener(this);
}
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width,
int height) {
Surface surface = new Surface(surfaceTexture);
if(mediaPlayer==null)
{
if(mediaPlayer == null){
mediaPlayer = new MediaPlayer();
}
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
mediaPlayer.start();
mediaState=MediaState.PLAYING;
}
});
mediaPlayer.setOnInfoListener(onInfoListener);
mediaPlayer.setOnBufferingUpdateListener(bufferingUpdateListener);
}
mediaPlayer.setSurface(surface);
mediaState=MediaState.INIT;
}
//停止播放
public void stop()
{
new Thread(new Runnable() {
@Override
public void run() {
try {
if(mediaState==MediaState.INIT)
{
return;
}
if(mediaState==MediaState.PREPARING)
{
mediaPlayer.reset();
mediaState=MediaState.INIT;
System.out.println("prepare->reset");
return;
}
if(mediaState==MediaState.PAUSE)
{
mediaPlayer.stop();
mediaPlayer.reset();
mediaState=MediaState.INIT;
System.out.println("pause->init");
return ;
}
if(mediaState==MediaState.PLAYING)
{
mediaPlayer.pause();
mediaPlayer.stop();
mediaPlayer.reset();
mediaState=MediaState.INIT;
System.out.println("playing->init");
return ;
}
} catch (Exception e) {
mediaPlayer.reset();
mediaState=MediaState.INIT;
}finally{
if(onStateChangeListener!=null)
{
onStateChangeListener.onStop();
}
}
}
}).start();
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
if(onStateChangeListener!=null)
{
onStateChangeListener.onSurfaceTextureDestroyed(surface);
}
return false;
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width,
int height) {
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
//开始播放视频
public void play(String videoUrl) {
if(mediaState==MediaState.PREPARING){
stop();
return;
}
mediaPlayer.reset();
mediaPlayer.setLooping(true);
try {
mediaPlayer.setDataSource(videoUrl);
} catch (Exception e) {
e.printStackTrace();
}
mediaPlayer.prepareAsync();
mediaState=MediaState.PREPARING;
}
//暂停播放
public void pause()
{
mediaPlayer.pause();
mediaState=MediaState.PAUSE;
}
//播放视频
public void start()
{
mediaPlayer.start();
mediaState=MediaState.PLAYING;
}
//状态(初始化、正在准备、正在播放、暂停、释放)
public enum MediaState
{
INIT,PREPARING,PLAYING,PAUSE,RELEASE;
}
//获取播放状态
public MediaState getState()
{
return mediaState;
}
}
package com.example.textureviewdemo;
import java.util.List;
import com.example.textureviewdemo.TextureVideoView.MediaState;
import com.example.textureviewdemo.TextureVideoView.OnStateChangeListener;
import com.xiaojiang.textureviewdemo.R;
import android.content.Context;
import android.graphics.SurfaceTexture;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.ViewHolder;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import android.widget.ProgressBar;
public class VideoAdapter extends RecyclerView.Adapter{
List mVideos;
Context mContext;
private VideoViewHolder lastPlayVideo=null;
public VideoAdapter(Context context,List videos) {
mContext=context;
mVideos=videos;
}
class VideoViewHolder extends ViewHolder{
public VideoViewHolder(View itemView) {
super(itemView);
}
TextureVideoView videoView;
ImageView imvPreview;
ImageView imvPlay;
ProgressBar pbWaiting;
ProgressBar pbProgressBar;
}
@Override
public int getItemCount() {
return mVideos.size();
}
@Override
public void onBindViewHolder(final VideoViewHolder viewHolder, final int position) {
viewHolder.videoView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if(lastPlayVideo==null)
{
lastPlayVideo=viewHolder;
}else
{
if(!viewHolder.equals(lastPlayVideo))
{
lastPlayVideo.videoView.stop();
lastPlayVideo.pbWaiting.setVisibility(View.GONE);
lastPlayVideo.imvPlay.setVisibility(View.VISIBLE);
lastPlayVideo=viewHolder;
}
}
TextureVideoView textureView = (TextureVideoView) v;
if(textureView.getState()==MediaState.INIT||textureView.getState()==MediaState.RELEASE)
{
textureView.play(mVideos.get(position));
viewHolder.pbWaiting.setVisibility(View.VISIBLE);
viewHolder.imvPlay.setVisibility(View.GONE);
}else if(textureView.getState()==MediaState.PAUSE)
{
textureView.start();
viewHolder.pbWaiting.setVisibility(View.GONE);
viewHolder.imvPlay.setVisibility(View.GONE);
}else if(textureView.getState()==MediaState.PLAYING)
{
textureView.pause();
viewHolder.pbWaiting.setVisibility(View.GONE);
viewHolder.imvPlay.setVisibility(View.VISIBLE);
}else if(textureView.getState()==MediaState.PREPARING)
{
textureView.stop();
viewHolder.pbWaiting.setVisibility(View.GONE);
viewHolder.imvPlay.setVisibility(View.VISIBLE);
}
}
});
viewHolder.videoView.setOnStateChangeListener(new OnStateChangeListener() {
@Override
public void onSurfaceTextureDestroyed(SurfaceTexture surface) {
viewHolder.videoView.stop();
viewHolder.pbWaiting.setVisibility(View.GONE);
viewHolder.imvPlay.setVisibility(View.VISIBLE);
viewHolder.pbProgressBar.setMax(1);
viewHolder.pbProgressBar.setProgress(0);
}
@Override
public void onPlaying() {
viewHolder.pbWaiting.setVisibility(View.GONE);
viewHolder.imvPlay.setVisibility(View.GONE);
}
@Override
public void onBuffering() {
viewHolder.pbWaiting.setVisibility(View.VISIBLE);
viewHolder.imvPlay.setVisibility(View.GONE);
}
@Override
public void onSeek(int max,int progress){
viewHolder.pbProgressBar.setMax(max);
viewHolder.pbProgressBar.setProgress(progress);
}
@Override
public void onStop() {
viewHolder.pbProgressBar.setMax(1);
viewHolder.pbProgressBar.setProgress(0);
}
});
}
@Override
public VideoViewHolder onCreateViewHolder(ViewGroup root, int position) {
View containerView=LayoutInflater.from(mContext).inflate(R.layout.videoitem, root, false);
VideoViewHolder videoViewHolder=new VideoViewHolder(containerView);
videoViewHolder.videoView=(TextureVideoView) containerView.findViewById(R.id.textureview);
videoViewHolder.imvPreview=(ImageView) containerView.findViewById(R.id.imv_preview);
videoViewHolder.imvPlay=(ImageView) containerView.findViewById(R.id.imv_video_play);
videoViewHolder.pbWaiting=(ProgressBar) containerView.findViewById(R.id.pb_waiting);
videoViewHolder.pbProgressBar=(ProgressBar) containerView.findViewById(R.id.progress_progressbar);
return videoViewHolder;
}
}
https://github.com/kidloserme/ListVideoPlayer
CSDN下载地址:http://download.csdn.net/detail/u013758734/9248269