1

I'm getting a crash in my adapter's getView() routine because it's being called with a position value of 6 and my datasource only has 6 items in it. So I assumed that the position parameter should be in a range of [0]-[5]? What determines the range of values in getView()'s position parameter?

Details:

the XML ...

<ListView
  android:id="@android:id/list"
  android:layout_height="match_parent"
  android:layout_width="match_parent"
  android:cacheColorHint="@color/colGrey"
  android:background="@color/colGrey"
  android:clickable="true"
  android:fastScrollEnabled="true"
  android:choiceMode="none"/>

...In MyListActivity, which is a ListActivity . . .

public static ListView lv;   // my ListView in the code

... during onCreate() . . .

   setContentView(R.layout.mylist);
   lv = getListView();

create the adapter and bind it . . .

mylistadapter = new MyListAdapter(MyListActivity.this);
setListAdapter(mylistadapter);   // bind the adapter

...the data source is an ArrayList called listItems. during the course of running the program its size varies and it may have been 15 earlier in program execution . . .

public static ArrayList<String>listItems=new ArrayList<String>();

... in my adapter, which is a BaseAdapter, my ovveride of getCount() looks like this . . .

@Override
public int getCount() {
    return listItems.size();
}

... when I call getCount() in getView() it returns 6, which is the number of items in the data source, but if I call lv.getCount() it returns 15. (any idea where this 15 is coming from?) Could that be why the adapter is calling getView with index too big?

user316117
  • 7,971
  • 20
  • 83
  • 158

1 Answers1

5

So I assumed that the position parameter should be in a range of [0]-[5]?

Yes.

What determines the range of values in getView()'s position parameter?

It will range from 0 to getCount()-1, where getCount() is implemented on the Adapter.

during the course of running the program its size varies and it may have been 15 earlier in program execution

You need to call notifyDataSetChanged() on the Adapter if you change the data, including changing the number of rows.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • I am calling notifyDataSetChanged(). But I'm calling it inside of a runnable (which I thought was the canonically correct way to do it). Is it possible that that thread isn't being executed until after it's too late, i.e, after getView() has already been called 6 times? If I'm sitting in a loop updating my dataset (listItems, above) how do I tell the adapter not to call getView() until I'm done? – user316117 May 15 '14 at 19:23
  • @user316117: "But I'm calling it inside of a runnable (which I thought was the canonically correct way to do it)." -- not necessarily. It needs to be called on the main application thread. "Is it possible that that thread isn't being executed until after it's too late" -- what thread? "If I'm sitting in a loop updating my dataset (listItems, above) how do I tell the adapter not to call getView() until I'm done?" -- you have to make all your changes on the main application thread. Fetch the data in the background, but **only** change what the `BaseAdapter` has on the main application thread. – CommonsWare May 15 '14 at 19:27
  • 1
    @user316117: Yes. So, on the main application thread, you change what your `BaseAdapter` holds onto in terms of its model data, then immediately call `notifyDataSetChanged()`. Android, later on the main application thread, will call `getCount()` to get the revised count, at which point the `ListView` and your `BaseAdapter` should be back in sync. – CommonsWare May 15 '14 at 19:51
  • In this SO article [link](http://stackoverflow.com/questions/3669325/notifydatasetchanged-example) they suggest a runnable of **runOnUiThread** What's the advantage of doing it that way? – user316117 May 15 '14 at 21:25
  • 1
    @user316117: `runOnUiThread()` runs the supplied `Runnable` on the main application thread. Using `runOnUiThread()` from a background thread is a perfectly fine way to get your `BaseAdapter`-updating logic, including the `notifyDataSetChanged()` call, to occur on the main application thread. – CommonsWare May 15 '14 at 21:29
  • I'm going to mark this as answered because it clearly has **something** to do with how I'm calling _notifyDataSetChanged()_. (I'm only doing it from 1 place where I do an _add()_ to my dataset then call _notifyDataSetChanged()_) When I embed logging in my code I can see that the crashes are happening when getView() is executed before _notifyDataSetChanged()_ gets executed. – user316117 May 15 '14 at 21:32