IllegalStateException with Froyo api 8


#1

Everything appeared to be working fine until I started to add some crimes on my Froyo 2.2 emulator. The first one is added, then after pressing Add for the second one this error occurs:

[code]FATAL EXCEPTION: main

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(16908298, class android.widget.ListView) with Adapter(class com.bignerdranch.android.criminalintent.CrimeListFragment$CrimeAdapter)]
[/code]

To check if I had made a mistake I imported ‘17_FileIO_CriminalIntent’ from the source download and ran this on the emulator. It gives me the same error.

Can anyone please help?


#2

Make sure the your CrimeListFragment updates its list content in onResume(). There should be a listing in the chapter on Fragment Arguments entitled “Reloading the list in onResume()” that contains this code.


#3

I have this code in CrimeListFragment…

@Override public void onResume() { super.onResume(); ((CrimeAdapter) getListAdapter()).notifyDataSetChanged(); }

…but the downloaded source has this instead…

@Override public void onActivityResult(int requestCode, int resultCode, Intent data) { ((CrimeAdapter)getListAdapter()).notifyDataSetChanged(); }

Both projects give the same error. Are you able to reproduce this on api 8? I don’t have the problem on api 17 emulator.


#4

You are correct. I’m able to replicate this in the solution as well.

The fix is to add an additional call to notifyDataSetChanged in onOptionsItemSelected:

    @TargetApi(11)
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.menu_item_new_crime:
                Crime crime = new Crime();
                CrimeLab.get(getActivity()).addCrime(crime);
                ((CrimeAdapter)getListAdapter()).notifyDataSetChanged();
                
                Intent i = new Intent(getActivity(), CrimeActivity.class);
                i.putExtra(CrimeFragment.EXTRA_CRIME_ID, crime.getId());
                startActivityForResult(i, 0);
                return true;

             ...
        } 
    }

I’ll add an item to the errata.


#5

Brilliant! Thank you for sorting that out so quickly. BTW, should the solution use onResume() rather than onActivityResult() for notifyDataSetChanged() ?


#6

It should use onResume().


#7

Excellent! Chapter 18 here I come :sunglasses: