最近在写一个和视频有关的项目,遇到了这个问题,开始使用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<VideoAdapter.VideoViewHolder>{ List<String> mVideos; Context mContext; private VideoViewHolder lastPlayVideo=null; public VideoAdapter(Context context,List<String> 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