最近在写一个和视频有关的项目,遇到了这个问题,开始使用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() {@Overridepublic 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() {@Overridepublic 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);}@Overridepublic 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() {@Overridepublic 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();}@Overridepublic boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {if(onStateChangeListener!=null){onStateChangeListener.onSurfaceTextureDestroyed(surface);}return false;}@Overridepublic void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width,int height) {}@Overridepublic 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;}}

下面是适配器,适配器中主要监听列表滚动,当一个Item隐藏之后,对应的TextureView就会销毁,在此时停止播放视频

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;}@Overridepublic int getItemCount() {return mVideos.size();}@Overridepublic void onBindViewHolder(final VideoViewHolder viewHolder, final int position) {viewHolder.videoView.setOnClickListener(new OnClickListener() {@Overridepublic 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() {@Overridepublic 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);}@Overridepublic void onPlaying() {viewHolder.pbWaiting.setVisibility(View.GONE);viewHolder.imvPlay.setVisibility(View.GONE);}@Overridepublic void onBuffering() {viewHolder.pbWaiting.setVisibility(View.VISIBLE);viewHolder.imvPlay.setVisibility(View.GONE);}@Overridepublic void onSeek(int max,int progress){viewHolder.pbProgressBar.setMax(max);viewHolder.pbProgressBar.setProgress(progress);}@Overridepublic void onStop() {viewHolder.pbProgressBar.setMax(1);viewHolder.pbProgressBar.setProgress(0);}});}@Overridepublic 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;}}

相关的布局文件以及Activity文件就不贴出来了,有兴趣的可以到此处下载源码:

https://github.com/kidloserme/ListVideoPlayer


CSDN下载地址:http://download.csdn.net/detail/u013758734/9248269



更多相关文章

  1. Android实现实时视频通话或监控方案
  2. 浅谈关于listview和button控件的背景
  3. Android接收UDP TS流实现边缓存边播放
  4. Android(安卓)开机视频
  5. Rexsee API介绍:Android视频播放,Rexsee的VideoPlayer函数说明与源
  6. Android文件命名规范
  7. Android(安卓)开发学习进程0.15 adb cardview framelayout 控件
  8. android 4.4 以上沉浸式状态栏和沉浸式导航栏管理,一句代码轻松实
  9. Android小程序实现音乐播放列表

随机推荐

  1. Android之SurfaceView学习(一)
  2. android 使用zxing生成中间嵌套logo的二
  3. android捕获全局异常,CrashHandler
  4. 导入android自带通讯录报错
  5. 修复Android Studio 3.5 AIDL报错问题
  6. ntfs-3g 移植到android
  7. Android培训班(24)
  8. 源码分析android的UI绘制流程
  9. Android-MediaPlayer播放网络音频
  10. android 通过intent打开 skype并传入号码