I've got a ListView
, each of item
of which contains a ToggleButton
. After I toggle it and then scroll up or down, the ListView is recycling the Views and so some of the others are mirroring the checked state of the ToggleButton
. I don't want this. How can I prevent it?

- 33,401
- 34
- 117
- 188
-
1post your getview() method there is problem in that – ingsaurabh Aug 03 '11 at 04:38
5 Answers
Add this two methods to your Adapter.
@Override
public int getViewTypeCount() {
return getCount();
}
@Override
public int getItemViewType(int position) {
return position;
}

- 2,724
- 25
- 16
-
38this is horrible. @RomainGuy would probably cry tears of blood if he stumbled upon this! You are basically telling the adapter to never recycle views. this will result in sluggish UI, lack of responsiveness. People, please don't use this! For the sake of your users! – njzk2 May 09 '14 at 20:51
-
DO NOT do this. This completely eliminates any view recycling. This accepted answer is the correct solution to this problem. NOT returning position in getItemViewType. – Seth Oct 06 '14 at 14:34
-
3Doing this is equivalent to not using array list, and just using ScrollView and calling `.addView` to throw all the rows in there... If you also have images in the rows - OutOfMemory exception is just around the corner... – Aviel Gross Nov 03 '14 at 13:07
-
27This does disable view recycling!! And this is exactly what I needed!! In my case the ListView has only 5-7 cells but with totally different layouts and contents. Recycling the view was creating a huge mess... Thanks a lot for this tweak!! – anemo Jan 18 '15 at 16:21
-
2I dunno... I have a list that will at max have 60 youtube thumbnails, titles, durations, and possibly links to download PDF files. For giggles, and to test this, I put over 100 of them in a list using this method. Not a single issue. Scrolls super smoothly. I've yet to test this on older devices, but this seems to be a great solution. – Riot Goes Woof Jul 13 '15 at 14:34
-
@LeoOlympian So why do you use ListView instead of populating views right into the LinearLayout? – æ-ra-code Feb 04 '16 at 16:19
-
1eh, use it carefull, only: applicable only if you known 100% list is small, and known ui on view use low mem; – user1005462 Aug 02 '16 at 15:57
-
is this solution feasible to use if the list size is around 50 to 70? – Prashanth Debbadwar Aug 25 '16 at 06:40
-
1people who are cursing this code, please guys its just a way, a code to disable recycling! if you are forcing some good tech code thing you have to suffer from some bad results like Sluggish UI, So if one have to force disable recycling of views; must have to suffer with sluggish UI, I think it would give just a minoooor lag and thats it. – Tech Nerd May 06 '17 at 21:19
-
-
1I had a list with only a textview .But each of its items had specific colors that change dynamically by the user.So there was no way but to implement that solution. – Omar Boshra Apr 22 '19 at 15:10
-
i like this,my application have many inputlist in many activity. A maximum of 30 views does not incur significant consumption, and these inputs can be managed uniformly through a listview\ – 卡尔斯路西法 May 18 '23 at 03:02
Android recycles list items for performance purposes. It is highly recommended to reuse them if you want your ListView to scroll smoothly.
For each list item the getView
function of your adapter is called. There, is where you have to assign the values for the item the ListView is asking for.
Have a look at this example:
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder holder = null;
if ( convertView == null )
{
/* There is no view at this position, we create a new one.
In this case by inflating an xml layout */
convertView = mInflater.inflate(R.layout.listview_item, null);
holder = new ViewHolder();
holder.toggleOk = (ToggleButton) convertView.findViewById( R.id.togOk );
convertView.setTag (holder);
}
else
{
/* We recycle a View that already exists */
holder = (ViewHolder) convertView.getTag ();
}
// Once we have a reference to the View we are returning, we set its values.
// Here is where you should set the ToggleButton value for this item!!!
holder.toggleOk.setChecked( mToggles.get( position ) );
return convertView;
}
Notice that ViewHolder
is a static class we use to recycle that view. Its properties are the views your list item has. It is declared in your adapter.
static class ViewHolder{
ToggleButton toggleOk;
}
mToggles
is declared as a private property in your adapter and set with a public method like this:
public void setToggleList( ArrayList<Boolean> list ){
this.mToggles = list;
notifyDataSetChanged();
}
Have a look at other custom ListView examples for more information.
Hope it helps.

- 11,460
- 4
- 56
- 71
-
2I'm aware of all of this. I expected the ListView not to reuse the views if the data inside them changed. – LuxuryMode Aug 03 '11 at 16:25
-
I don't get your point. I can't imagine why would you need a new View every time. Actually, I think the reuse of Views is a great Android feature. – Xavi Gil Aug 03 '11 at 19:19
-
3Point well taken and I'm not arguing against the benefit of reusing views. But isn't it reasonable for me to try to get each item's toggleButton to retain its proper state (checked or not checked)? – LuxuryMode Aug 04 '11 at 00:05
-
Well, if your ListView is long, not reusing means wasting memory. In mobile devices you have to be careful with that. Besides, you should keep the state of your items in your Model not in your Views. Anyway answering your question, if you want a View for each Item just create it every time `getView` is called (forget about the `if ... else ...` statement). I don't recommend it though. – Xavi Gil Aug 04 '11 at 07:20
-
Buffalo - I've got a view with different components depending on (in my case) the underlying device. Just needs slightly more complex initialisation code. Check out http://www.youtube.com/watch?v=wDBM6wVEO70 – Ghoti Jul 20 '12 at 15:57
-
Seems like this is bad practice as a class being used with an entirely different dataset should warrant a new instance of that class. – Ron E Mar 22 '14 at 17:36
-
1@LuxuryMode : Can you please post the solution how you managed it to resolve ? I too am in same position. For each listview item, it has a 'DATE' in it's class and I check each time if the Date is already not in an arraylist then add date into that listview item and add that into the arraylist too. Now when getView is called again, as the date is already in the date arraylist, it deletes the date from that and now despite many hours i'm stuck at it.. can you help ? – Shumail Jul 20 '14 at 21:11
-
Hey @XaviGil in my app the list view doesn't scroll smoothly. I tried everything Google recommends including loading bitmaps in the background. I knew about list view recycling, but I thought Android automatically recycles list view elements. So is that false and do you have to implement recycling on your own as you've shown? I really hope so because it would mean fixing my scrolling issues. – Anshu Dwibhashi Apr 09 '16 at 03:54
-
If you have different types of data to display you can write a Master Adapter with different Slaves. It is up to you as a software designer to manage that in place. Sorry, maybe no help for somebody. But just mentioned it is possible! @Buffalo – redestructa Aug 01 '16 at 21:00
-
can anyone tell me where to call this setToggleList from? Especially if I dont have a holder but a custom view that I am inflating? – Aditya Sawant Jan 16 '17 at 10:54
-
thanks for the comments above your code lines, those helped me a lot! – Pier Giorgio Misley May 10 '17 at 16:14
-
this has another problem. when set the first post it's automatically set to last post. – Ks Sjkjs Jun 08 '18 at 12:31
-
I implemented using this View holder pattern, but the issue still remains! My view requires toggling the visibility of an ImageView icon. Anybody know what else could be going wrong? – Ron Jul 13 '18 at 00:51
You could use a HashMap
to save your buttons state:
private Map<Integer,Boolean> listMapBoolean = new HashMap<Integer,Boolean>();
toggleButton.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
listMapBoolean.put(position, true);
} else {
listMapBoolean.put(position, false);
}
}
});
and after inflating the view you read the HashMap
to see if it was checked or not:
for (Entry<Integer, Boolean> entry : listMapBoolean.entrySet()) {
if (entry.getKey().equals(i)) {
if(entry.getValue()) {
System.out.println("ToggleButton is checked!");
} else {
System.out.println("ToggleButton is not checked!");
}
}
}
Not sure if it helps in your way. I had also problems with recycling my EditText
in my ListView
.

- 6,974
- 4
- 45
- 40

- 469
- 6
- 9
-
Of course you will need to initially set all the tooglebuttons to false. – Jan Ziesse Jun 06 '14 at 07:57
This would make it so slow for large lists. But inside getView()
, you can use:
if (listItemView == null || ((int)listItemView.getTag()!=position)) {
listItemView = LayoutInflater.from(context).inflate(R.layout.edit_text_list_item,
parent, false);
}
listItemView.setTag(position);
// set inner Views data from ArrayList
...
The tag is an Object
that is associated with the View
. And you check whenever you recycle it if you can recycle it or not. This makes each list item be inflated and nothing will be recycled.
This also should prevent deleting text from EditText
inside the ListView
and also prevent images from being reordered or messed up if your ListView
has images in it.

- 416
- 4
- 12
May be you should try creating your own list view with scroll view and a container that holds the children that are added to the container programatically. set the tag for identifying the child or you could use the order of the child for that

- 10,106
- 7
- 39
- 60