I have a GridView that is recycling child views using an adapter. Each child view is composed of an ImageView with a TextView overlayed on top. The problem I'm seeing is that as I scroll and new images come into view, the image of other cells in the grid can also change to the images that are coming into view.
After debugging I can see that this is because when a new row comes into view, getView() is called on the adapter to get the view for the new row. However the view being passed into the method, that android wants me to recycle, is actually still in view. So when I update the image of the view it gives me, I end up changing the image of another item in the grid too.
Does anyone know what could cause this?
Activity
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/snapshot_list_swipe_refresh"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_snapshot_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.vellocet.snapshotviewer.SnapshotListActivity">
<GridView
android:id="@+id/snapshot_grid"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="5dp"
android:drawSelectorOnTop="true"
android:gravity="center"
android:numColumns="2"
android:stretchMode="columnWidth"
android:verticalSpacing="0dp"
android:horizontalSpacing="0dp"
android:focusable="true"
android:clickable="true"/>
</RelativeLayout>
</android.support.v4.widget.SwipeRefreshLayout>
Adapter:
private class SnapshotListAdapter extends BaseAdapter {
private final Context context;
private List<Snapshot> snapshots;
public SnapshotListAdapter(Context context, List<Snapshot> snapshots) {
this.context = context;
snapshots = snapshots;
}
@Override
public int getCount() {
return snapshots.size();
}
@Override
public Object getItem(int i) {
return i < snapshots.size() ? snapshots.get(i) : null;
}
@Override
public long getItemId(int i) {
return i;
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
ViewHolder viewHolder;
if (view == null) {
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
view = inflater.inflate(R.layout.snapshot_grid_item_layout, viewGroup, false);
viewHolder = new ViewHolder();
viewHolder.image = (ImageView)view.findViewById(R.id.snapshot_grid_item_imageview);
viewHolder.text = (TextView) view.findViewById(R.id.snapshot_grid_item_textview);
view.setTag(viewHolder);
view.setLayoutParams(new GridView.LayoutParams(
GridView.LayoutParams.MATCH_PARENT,
(int)getResources().getDimension(R.dimen.snapshot_grid_item_height)));
}
else {
viewHolder = (ViewHolder)view.getTag();
}
final Snapshot snapshot = snapshots.get(i);
viewHolder.snapshot = snapshot;
viewHolder.image.setImageDrawable(null);
viewHolder.updateText();
snapshot.getSnapshotFiles(new GetSnapshotCallback(viewHolder, snapshot));
return view;
}
}
Thanks for any help
My mistake. Although a view that is still on screen is being recycled, a new view is subsequently created for the original position.
E.g If position 0 is on screen and you scroll to bring position 8 into view, the view for position 0 is recycled into position 8 even though position 0 is still on screen. However it will then call another createView for position 0, passing in no recycle view, so a new instance is created. Slightly odd process but it's not causing the problem i'm seeing with images appearing in multiple image views.