johan
johan

Reputation: 6666

Crash when updating adapter in listview

Im using a Sectioned adapter. Each section has a "subAdapter".

I get a problem when im removing all sections, and adding new ones. If the new amount of Sections > old amount of sections.

10-27 08:08:33.789: ERROR/AndroidRuntime(21550): java.lang.ArrayIndexOutOfBoundsException
10-27 08:08:33.789: ERROR/AndroidRuntime(21550):     at android.widget.AbsListView$RecycleBin.addScrapView(AbsListView.java:5283)
10-27 08:08:33.789: ERROR/AndroidRuntime(21550):     at android.widget.AbsListView.trackMotionScroll(AbsListView.java:4092)
10-27 08:08:33.789: ERROR/AndroidRuntime(21550):     at android.widget.AbsListView.onTouchEvent(AbsListView.java:2523)
10-27 08:08:33.789: ERROR/AndroidRuntime(21550):     at android.widget.ListView.onTouchEvent(ListView.java:3733)
10-27 08:08:33.789: ERROR/AndroidRuntime(21550):     at android.view.View.dispatchTouchEvent(View.java:3885)
10-27 08:08:33.789: ERROR/AndroidRuntime(21550):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:903)
10-27 08:08:33.789: ERROR/AndroidRuntime(21550):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:942)
10-27 08:08:33.789: ERROR/AndroidRuntime(21550):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:942)
10-27 08:08:33.789: ERROR/AndroidRuntime(21550):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:942)

From what I've read this is a problem with getViewTypeCount. Im guessing that the method isn't called when Im updating the adapter and calling adapter.notifyDataSetChanged();

The problem doesn't occur if i set a new instance of the adapter as listAdapter.

How can I solve this problem? Can I force the activity to recall getViewTypeCount ?

Upvotes: 0

Views: 952

Answers (2)

Blundell
Blundell

Reputation: 76466

Hack Alert

If you are using Etsy's StaggerredGridView (and copy the code in as a module), or use something that extends AbsListView you can get it to recall getViewTypeCount() whenever you call notifyDataSetChanged().

Here is the original code (for StaggeredGridView - ExtendableListView.java:

@Override
public void setAdapter(final ListAdapter adapter) {
    // ... other code

    if (mAdapter != null) {
        mAdapter.registerDataSetObserver(mObserver);
        mRecycleBin.setViewTypeCount(mAdapter.getViewTypeCount());
    }

    requestLayout();
}

As you can see mAdapter.getViewTypeCount() is only called when you call setAdapter. So if we copy this code and move it to the place notifyDataSetChanged() is called we can update our adapter with new types!

Which is here (for StaggeredGridView - ExtendableListView.java:

    class AdapterDataSetObserver extends DataSetObserver {

        private Parcelable mInstanceState = null;

        @Override
        public void onChanged() {
            // other code

            mRecycleBin.clearTransientStateViews();
            mRecycleBin.setViewTypeCount(mAdapter.getViewTypeCount()); // ADD THIS

            // other code
            requestLayout();
        }

        // more methods
     }

I have no idea if this effects performance or recycling, by reading this you take all blame for the above code. :-)

Upvotes: 0

CommonsWare
CommonsWare

Reputation: 1006744

Im guessing that the method isn't called when Im updating the adapter and calling adapter.notifyDataSetChanged();

Correct. getViewTypeCount() is only called once.

How can I solve this problem?

Do not change the value of getViewTypeCount() for the lifetime of your adapter.

Can I force the activity to recall getViewTypeCount ?

Not that I am aware of, sorry.

Upvotes: 2

Related Questions