2

I've been learning about creating custom ArrayAdapters and have familiarized myself with overriding an ArrayAdapter's getViewTypeCount and getItemViewType methods.

Why does the Android View API care about the 'number of possible view types' returned by getViewTypeCount ? And, as the programmer, why should I care?

ybakos
  • 8,152
  • 7
  • 46
  • 74
  • 1
    possible duplicate of [Why do recipes promote overriding getItemViewType and getViewTypeCount when it doesn't seem necessary?](http://stackoverflow.com/questions/10270143/why-do-recipes-promote-overriding-getitemviewtype-and-getviewtypecount-when-it-d) – CommonsWare Apr 22 '12 at 17:28
  • It's related (I'm the author of both) but I chose to keep the questions atomic/separated. – ybakos Apr 22 '12 at 17:41
  • To re-emphasize the point of this question, realize that this question isn't about recycling or using custom views -- I'm asking, "why do Android gotta know/care 'bout the number of custom views, since it retrieves that specific view type from getItemViewType?" – ybakos Apr 23 '12 at 06:33

3 Answers3

3

I've just reviewed the Android source to see exactly where getViewTypeCount is used. It's in the abstract AbsListView class' inner RecycleBin class' setViewTypeCount method.

This setViewTypeCount method is used to specify the initial size of the ArrayList<View> of scrapViews. This ArrayList itself is an ArrayList of ArrayList<View>s -- one for each "view type count."

Furthermore the value returned by getViewTypeCount is assigned to RecycleBin's member variable mViewTypeCount. This member is used to control the logic for recycling for cases where there is only one vs. many views throughout a handful of methods in the RecycleBin class(as everyone has been alluding to).

So the answer is, I believe, that getViewTypeCount is used by RecycleBin so that it knows whether it has just one or numerous Views to handle. So to speak.

(Thanks everyone for opening my eyes to recycling and motivating me to read the source.)

ybakos
  • 8,152
  • 7
  • 46
  • 74
2

Commonsware's answer on your previous question explained very well why do you need to care about those methods. Here is a small example:

You have a ListView with 100 rows and 3 types of rows:

  1. a simple TextView
  2. a custom view (very complex)
  3. an AnalogClock view

You ListView starts like this:

  • position 0: TextView <= first visible position
  • position 1: custom view
  • position 2: custom view
  • position 3: TextView
  • position 4: AnalogClock <= last visible position
  • position 5: custom view <= first invisible position(here android will provide a recycled view)
  • position 6: TextView

If you don't implement those methods then android will simply recycle the views not taking in consideration the type of rows. So in the example above, when the user scrolls the ListView down the getView method will be called for row 5 with a recycled view(the row 0 that isn't visible anymore), a TextView(convertView will not be null for this position). As you see this isn't the view you would expect at that position. Because in the getView method you have something like this:

   //...
       if (convertView == null) {     
          // inflate views
       } else {
         //just use it    
   //...

you'll end up setting data on a row that should be a custom view(very complex) but instead get a simple TextView. This will get worse as you further scroll the ListView up and down.

If you do implement those methods then android will know that the getView method will expect 3 types of rows. When row 5(from the previous example) needs to be shown android will call getItemViewType to see what type of view the getView method expects for that position(position 5). If a recycled view of that type is found(previously recycled) then the getView method will be called with convertView set to that recycled view, if not then the getView will be called with convertView set to null. As you scroll the ListView to show the position 5 the(only) recycled view will be the simple TextView. The getView method expects a custom view(very complex) and as a recycled view isn't found with that type then the convertView will be null and you get the chance to inflate it.

If you scroll the ListView to show position 6 the view from position 1(that isn't on the screen anymore) will be recycled so the ListView has now two views of different types(TextView and a custom view(very complex)). Then the getItemViewType will be called again and for this position the getView method requires a TextView. A recycled view of this type exists so the getView method will be called with convertView set to this recycled TextView. If you further scroll the ListView and the getView requires a TextView or a custom view one of those recycled views(with the correct type) will be supplied. Also, eventually a view of type AnalogCLock will be recycled so the ListView will have recycled views of each list row type to reuse.

user
  • 86,916
  • 18
  • 197
  • 190
  • I really like this explanation of recycling. However, this answer is more relevant to [Why do recipes promote overriding getItemViewType and getViewTypeCount when it doesn't seem necessary?](http://stackoverflow.com/questions/10270143/why-do-recipes-promote-overriding-getitemviewtype-and-getviewtypecount-when-it-d). My question is, specifically, why does the number of custom views matter, per `getViewTypeCount` ? – ybakos Apr 23 '12 at 06:30
  • 1
    @ybakos: "My question is, specifically, why does the number of custom views matter, per getViewTypeCount ?" -- that drives the number of object pools it maintains for recycling, AFAIK. You are welcome to sift through the `AdapterView` code to try to get at more details. – CommonsWare Apr 23 '12 at 10:40
1

In the reference, it says "Each type represents a set of views that can be converted in getView(int, View, ViewGroup)."

If the views are different, then they cannot be recycled with incompatible other views. So if this method returns anything different from 1 the standard onView recycling code will not work anymore.

ybakos
  • 8,152
  • 7
  • 46
  • 74
user387184
  • 10,953
  • 12
  • 77
  • 147