Few months ago I had to work on a screen in an Android app where we had seekbar controls inside a ListView item. When an item inside the ListView is selected we would show the seekbar inside the item and allow the user to interact with it. As the user moves the seekbar thumb back and forth we update two TextView fields within the ListView item’s layout. I created a ListView using an adapter and in the adapter class I was inflating/reusing item layout that had a Seekbar and two TextView fields. In the onProgressChanged event of the Seekbar I was updating the two TextViews. I noticed that changing seekbar thumb position with touch was extremely sluggish. My initial thought was this sluggishness is due to the fact that we are updating two TextViews and before updating them we are doing some string formatting operations.
I started my investigation and found that if I don’t update the TextViews then performance improves. But then I thought there must be something else as updating a few text fields should not overload the UI thread. I decided to create a sample project to test my hypothesis. First I added a single Seekbar with two TextViews and was updating them in the Seekbar onProgressChanged event. Everything was working very smoothly and no sluggishness. Then I built similar UI where I had Seekbars inside a ListView with two TextViews. On Seekbar progress change I was updating the two TextViews. Noticed same sluggishness. That gave me a clue that as soon I put Seekbar inside the ListView the Seekbar performance goes down. Then I thought of a work around which was not to use ListView and instead use a LinearLayout and add each item in the list manually in the code. This solution got rid of sluggishness I was experiencing.
At this point I had a solution that was working without any issues but I was having hard time accepting that using Seekbars inside a ListView can cause performance issue. I started looking at the adapter class and noticed that I was inflating the list view item layout each time and not reusing them. As per the guidelines we should check if convertView is null only then we should inflate the item layout otherwise reuse the existing view. So I made the modification to the code to reuse the converView if it is not null. And that was it. The sluggishness in Seekbar was gone.
At this point I had discovered two things, a work around for the ListView performance issue and a mistake that we should not inflate list view item layout each time in adapter’s getView function because it can cause significant performance issues that you will spend hours trying to figure out. ListView is a very efficient way displaying lot of content on a small screen. When a ListView loads it shows as many items as can fit into the screen window and as the user scrolls, it reuses those item view’s and populates them with new data. This way we don’t load views that are not visible to user. This results smooth ListView performance.
Here is the Github link for my sample project SliderApplication
https://github.com/niveditau/SliderApplication