Syed Fahad
Syed Fahad

Reputation: 147

Android ListView and GridView repeating changed item during scroll

I am wondering why ListView or GridView used old items during scroll? I have a list view more than 500 products i am showing in list view . Each list item has 4 columns the last column is a ImageView showing status as active or inactive. Whenever i marked ImageView as active then after scrolling periodically every item automatically changed its ImageView as active.

Let suppose if i clicked on 6th Items and make its ImageView as active then during scroll i see that 12th , 18th , 24th and so on also changed as active

Upvotes: 0

Views: 586

Answers (2)

kris larson
kris larson

Reputation: 30985

In order to optimize the scrolling experience, ListView and GridView will re-use item views to avoid having to inflate/instantiate a view for every list item.

That's why getView has a parameter of type View called convertView. When convertView is null, you need to inflate a new view for the item. When it is not null, that means you can re-use this view to avoid the overhead of inflation.

The downside is that this "recycled" item view will have garbage in it from the last time it was displayed, and you have to reset everything in the view to match the list item.

So a common mistake that new Android developers make is to not have a model representation of everything in the view. For example, if your list item can show a status of active or inactive, then the model for your list item should probably have a boolean property called mActive.

The model for the list has to have the entire current state of the list at any given time, so that it can be recreated whenever the ListView decides it needs to redisplay its list items.

So what you need to do is basically four things:

  • Add the property to your list item model:

        boolean mActive;    // this can be private with getter/setter
    
  • Create an adapter method for changing the state. For example:

        public void toggleItemActive(int position) {
    
            mListItem.get(position).mActive = ! mListItem.get(position).mActive;
            notifyDataSetChanged();
        }
    

    Calling notifyDataSetChanged() here is very important.

  • Use this property in your getView override:

        imageView.setImageResource(item.mActive ? R.drawable.active : R.drawable.inactive);  // or however you are doing it
    
  • Set the property from your event handler:

        listView.setOnItemClickListener(new OnItemClickListener) {
    
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                MyAdapter adapter = (MyAdapter) parent.getAdapter();
                adapter.toggleItemActive(position);
            }
        });
    

Now your ListView will correctly display your list items.

Upvotes: 1

Varini Ramesh
Varini Ramesh

Reputation: 251

I think you are using viewholder inside getView() method of your custom adapter. When you are using view holder you will be reusing the views. From your description it looks like, your device can diaply 6 list items at a time. So 6th, 12th (6th position + 6-size of screen), 18th (12th position + 6-size of screen), 24th etc will all be using the same view. Therefore, when 6th item is changed the related 12th, 18th, 24th etc items will also be changed.

Upvotes: 0

Related Questions