TpoM6oH
TpoM6oH

Reputation: 8575

ListView IllegalStateException in an array[]-based adapter

I have an adapter, it is a nested class:

protected abstract class MyAdapter extends BaseAdapter {

    private Context context;
    private Data[] data;

    protected MyAdapter(Context context) {
        this.context = context;
    }

    public void setData(Data[] data) {
        this.data = data;
    }

    @Override
    public int getCount() {
        return data == null || data.length == 0 ? 0 : data.length * 2;
    }

    @Override
    public Object getItem(int i) {
        return data == null ? null : data[i / 2];
    }

    @Override
    public long getItemId(int i) {
        return i;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ...
    }
         ///other methods not modifying data[]
}

I use setData(Data[] data) only in one place:

public void setNewData(Data[] data) {
    if (!Arrays.deepEquals(myAdapter.data, data)) {
        myAdapter.setData(data);
        myAdapter.notifyDataSetChanged();
    }

    updateVisibility();
}

And access to the variable in one place:

protected void updateVisibility() {
    Data[] localData = myAdapter.data;

    if (localData != null && localData.length > 0) {
        //do smth not related to localData[]
    } 
}

In google play I see that users get this error:

java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. [in ListView(2131427598, class android.widget.ListView) with Adapter]
at android.widget.ListView.layoutChildren(ListView.java:1544)
at android.widget.AbsListView.onTouchEvent(AbsListView.java:4141)
at android.view.View.dispatchTouchEvent(View.java:7350)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2464)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197)

But can't understand from where it comes.

ADDED:

I think that here is the reason:

In a child class I override the getCount() method and it returns different numbers based on the orientation.

    @Override
    public int getCount() {
        int count = super.getCount();

        if (isPortrait(context.getResources())) {
            count++;  
        }

        return count;
    }

I think that I should update the listView's cached item count somewhere here. What do you think? Am I right?

Upvotes: 0

Views: 124

Answers (2)

Leonidos
Leonidos

Reputation: 10518

Are you sure that you dont use data array that comes to setNewData anywhere else? Maybe you reuse this array and update it somehow? This exception is thrown in case when internal listView's item count not equals adapter's getCount when listView layout it's items. Recheck your code.

Upvotes: 2

ranjk89
ranjk89

Reputation: 1570

Where are you calling setNewData?

If you are calling it after the adapter has been initialized, call

http://developer.android.com/reference/android/widget/BaseAdapter.html#notifyDataSetChanged()

Upvotes: 0

Related Questions