I am making an app where I have multiple texture views in a listview. I am using a list array adapter I always use so I know that I am properly recycling each list view item and that I am setting the correct url for the video in each texture view. However, If my list contains more than three videos, they start to "duplicate" themselves, meaning that the fourth list item renders, but video one renders in it instead of video four. Also, when I scroll down and back up, sometimes the video resource I have attacted to that texture view also changes like they are being "re-rendered" by the adapter. Should I not recycle the views? current relevant code:
public class VideoListAdapter extends ArrayAdapter<videoitem> {
Context context;
int phonewidth;
int videoPlaying =0;
List<MediaPlayer> playerList = new ArrayList();
int pos;
private final ImageDownloader mDownload = new ImageDownloader();
public VideoListAdapter(Context context, int resourceId, List<videoitem> items) {
super(context, resourceId, items);
this.context = context;
phonewidth = context.getResources().getDisplayMetrics().widthPixels;
}
private class ViewHolder {
RelativeLayout wrapper;
InlineVideoPlayer videoPoster;
TextView numberOfLikes;
TextView numberOfDislikes;
ImageView UserIcon;
TextView userName;
TextView created;
ProgressBar p;
LinearLayout l;
}
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
final videoitem rowItem = getItem(position);
pos = position;
LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = mInflater.inflate(R.layout.videoitem,parent, false);
holder = new ViewHolder();
holder.wrapper = (RelativeLayout) convertView.findViewById(R.id.videoholder);
holder.l = (LinearLayout) convertView.findViewById(R.id.inlineVideoPlayer1);
// holder.videoPoster.setVideo("http//hub60.com/app/videos/" + rowItem.getVideo());
holder.UserIcon = (ImageView) convertView.findViewById(R.id.imageView1);
holder.numberOfDislikes = (TextView) convertView.findViewById(R.id.textView3);
holder.numberOfLikes = (TextView) convertView.findViewById(R.id.ratinglikes);
holder.created = (TextView) convertView.findViewById(R.id.textView2);
holder.userName = (TextView) convertView.findViewById(R.id.textView1);
holder.numberOfDislikes.setText(Integer.toString(position));
holder.numberOfLikes.setText(rowItem.getLikes());
holder.userName.setText(rowItem.getVideo());
holder.created.setText(rowItem.getCreated());
mDownload.download(rowItem.getIcon(), holder.UserIcon, null);
holder.l.getLayoutParams().height = phonewidth;
// vid.setLayoutParams(new LayoutParams(
// LayoutParams.MATCH_PARENT,
// LayoutParams.MATCH_PARENT));
convertView.setTag(holder);
} else{
holder = (ViewHolder) convertView.getTag();
holder.numberOfDislikes.setText(Integer.toString(position));
holder.numberOfLikes.setText(rowItem.getLikes());
holder.userName.setText(rowItem.getVideo());
holder.created.setText(rowItem.getCreated());
mDownload.download(rowItem.getIcon(), holder.UserIcon, null);
convertView.setId(position);
}
InlineVideoPlayer vid = new InlineVideoPlayer(rowItem.getVideo(),context);
((LinearLayout) holder.l).addView(vid);
return convertView;
}
in this particular case I took it out of the if/else deciding if the holder was empty and just added the view in question at the end. However I also had it in the if/else statement and am still experiencing the same behavior.
Custom texture view class
public class InlineVideoPlayer extends TextureView implements SurfaceTextureListener{
Context context;
MediaPlayer mp;
String url;
Surface surface;
SurfaceTexture s;
public InlineVideoPlayer(Context context, AttributeSet attrs)
{
super(context, attrs);
this.context = context;
}
public InlineVideoPlayer(String ur,Context context)
{
super(context);
this.setSurfaceTextureListener(this);
this.url = ur;
this.context = context;
// startVideo();
//Log.d("url",this.url);
}
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int arg1, int arg2) {
this.s = surface;
Log.d("url",this.url);
startVideo(surface);
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture arg0) {
return true;
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture arg0, int arg1,int arg2) {
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture arg0) {
}
public void setVideo(String url)
{
this.url = url;
}
public void startVideo(SurfaceTexture t)
{
this.surface = new Surface(t);
this.mp = new MediaPlayer();
this.mp.setSurface(this.surface);
try {
Uri uri = Uri.parse(this.url);
this.mp.setDataSource(this.context, uri);
this.mp.prepareAsync();
this.mp.setOnPreparedListener(new OnPreparedListener() {
public void onPrepared(MediaPlayer mp) {
mp.setLooping(true);
mp.seekTo(2000);
mp.start();
// mp.pause();
}
});
} catch (IllegalArgumentException e1) {
e1.printStackTrace();
} catch (SecurityException e1) {
e1.printStackTrace();
} catch (IllegalStateException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
try {
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
}
try {
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
}
thank you in advance