Video showing in wrong order when using TextureView in ListView
I have a Listview that displays a video in some rows so that the user can view the video through the listview using a TextureView. So far the videos are loading and playing correctly, but they seem to appear in the wrong order at times when scrolling. I suppose it has something to do with looking at the adapter utility, but I'm not sure how to fix it.
here is my implementation
There is a getView that handles rendering of the views, and then an AsyncTask is created, triggered by getView to set up the MediaPlayer for each view.
@Override
public View getView(int position, View view, ViewGroup parent) {
final ViewHolder holder;
final VoucherItem vItem = items.get(position);
if (view == null) {
view = inflater.inflate(R.layout.voucher_row, parent, false);
holder = new ViewHolder();
holder.list_img = (ImageView) view.findViewById(R.id.list_img);
holder.vid_play = (ImageView) view.findViewById(R.id.vid_play);
holder.video = (TextureView) view.findViewById(R.id.texture_video);
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
if (!vItem.photo.equals(""))
Picasso.with(context).load(vItem.photo).fit().centerCrop()
.into(holder.list_img);
else
Picasso.with(context).load(R.drawable.default_spuare).fit()
.centerCrop().into(holder.list_img);
if (!vItem.photo.equals("")){
holder.vid_play.setVisibility(View.GONE);
holder.video.setVisibility(View.GONE);
holder.list_img.setVisibility(View.VISIBLE);
} else {
holder.video.setVisibility(View.VISIBLE);
holder.list_img.setVisibility(View.GONE);
holder.video.setSurfaceTextureListener(new SurfaceTextureListener() {
@Override
public void onSurfaceTextureUpdated(SurfaceTexture arg0) {
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture arg0, int arg1,
int arg2) {
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture arg0) {
return false;
}
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int arg1, int arg2) {
final MediaPlayer mediaPlayer = new MediaPlayer();
holder.vid_play.setTag(mediaPlayer);
new SetVideotask().execute(surface, vItem, mediaPlayer, holder.vid_play);
}
});
}
}
return view;
}
class SetVideotask extends AsyncTask<Object, Integer, String>{
@Override
protected String doInBackground(Object... o) {
// TODO Auto-generated method stub
final SurfaceTexture s = (SurfaceTexture) o[0];
final VoucherItem item = (VoucherItem) o[1];
final MediaPlayer mediaPlayer = (MediaPlayer) o[2];
final View v = (View) o[3];
mediaPlayer.setSurface(new Surface(s));
try {
mediaPlayer.setDataSource(item.video);
mediaPlayer.prepare();
mediaPlayer.start();
//I do this so there is a frame in the video to act as a preview
Thread.sleep(100);
mediaPlayer.pause();
mediaPlayer.setOnErrorListener(VoucherAdapter.this);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
static class ViewHolder {
ImageView list_img;
ImageView vid_play;
TextureView video;
}
@Override
public boolean onError(MediaPlayer arg0, int arg1, int arg2) {
return true;
}
source to share
This is because your instances AsyncTask
created in onSurfaceTextureAvailable
might not end sequentially, and on scrolling, the stream created for the new view
one might end before the stream processed view
(so the old data is loaded).
I managed to solve this case by creating a single thread pool that I terminate on scrolling.
Also, this is the final download question ListView
.
source to share