2

I'm trying to get a List it's size but when doing this I'm getting a ConcurrentModificationException on the size() method. This is weird because I'm not trying to modify the list while iterating over it. Here's some of my code that might have caused it but I can't see the problem with it.

The main method:

private void setupCharacterGrid() {

    currentCharacters.add(0, new Character("add", "add"));
    if (currentCharacters.size() < 9) {
        sub(0, currentCharacters.size(), currentCharacters.size());
    } else {
        sub(0, 9, 9);
    }

    fillGrids();

    charPager.setAdapter(new CustomPagerAdapter(characterGrids));
    charPager.setCurrentItem(0);

}

The sub method (the method where the list is filled) please note that the dividedCharList is of the type: List> where Character is a custom POJO.

private void sub(int start, int end, int n) {
    int size = currentCharacters.size();
    if (start > size) {
        return;
    } else if (start == size) {
        // new list(currentcharacters.get(start))
        // check if it fits on the previous grid
        List<Character> lastGrid = dividedCharList.get(dividedCharList
                .size() - 1);
        if (lastGrid.size() < 9) {
            lastGrid.add(currentCharacters.get(start - 1));
        } else {
            List<Character> finalCharList = new ArrayList<Character>();
            finalCharList.add(currentCharacters.get(start - 1));
            dividedCharList.add(finalCharList);
        }
        return;
    } else {
        if (size < start + n) {
            sub(start, end, n--);
        } else {
            // new list(currentcharacters.sublist(start, end);
            // end = end + n;
            // start = end + 1
            dividedCharList.add(currentCharacters.subList(start, end));
            start = end + 1;
            end = end + n;
            sub(start, end, n);
        }
    }
}

The method where the exception occurs when trying to get the size:

private synchronized void fillGrids() {
    for (int i = 0; i < dividedCharList.size(); i++) {
        GridView gridView = new GridView(this);
        gridView.setNumColumns(3);
        CharacterGridAdapter aa = new CharacterGridAdapter(this,
                R.layout.charactergrid_cell, dividedCharList.get(i));
        gridView.setAdapter(aa);
        characterGrids.add(gridView);
    }
}

Please note that the exception also occurs when I'm trying to iterate trough the List and try to get a value and display it in a log

Edit

I've just noticed the exception occurs while calling gridView.setAdapter(), the getCount method of the ArrayAdapter throws the ConcurrentModificationException

Edit2

Here's the stacktrace, it might help:

01-24 13:03:44.942: E/AndroidRuntime(15336): FATAL EXCEPTION: main
01-24 13:03:44.942: E/AndroidRuntime(15336): java.util.ConcurrentModificationException
01-24 13:03:44.942: E/AndroidRuntime(15336): at                 java.util.AbstractList$SubAbstractList.size(AbstractList.java:360)
 01-24 13:03:44.942: E/AndroidRuntime(15336):   at    android.widget.ArrayAdapter.getCount(ArrayAdapter.java:330)
 01-24 13:03:44.942: E/AndroidRuntime(15336):   at android.widget.GridView.setAdapter(GridView.java:182)
 01-24 13:03:44.942: E/AndroidRuntime(15336):   at xx.ProfileActivity.fillGrids(ProfileActivity.java:111)
 01-24 13:03:44.942: E/AndroidRuntime(15336): 
 xx.ProfileActivity.setupCharacterGrid(ProfileActivity.java:96)
 01-24 13:03:44.942: E/AndroidRuntime(15336):   at xx.ProfileActivity.access$6(ProfileActivity.java:87)

On request the Adapter code

public class CharacterGridAdapter extends ArrayAdapter<Character> {

private Context context;
private List<Character> objects;
private int resource;

public CharacterGridAdapter(Context context, int resource, List<Character> listChar) {
    super(context, resource);
    this.context = context;
    this.objects = listChar;
    this.resource = resource;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View rowView = convertView;
    if (rowView == null) {
        LayoutInflater inflater = ((Activity) context).getLayoutInflater();
        rowView = inflater.inflate(R.layout.charactergrid_cell, null);
    } else {
    }
    return rowView;
}

}

Anyone who could help me with this one?

Tim Kranen
  • 4,202
  • 4
  • 26
  • 49

1 Answers1

2

Remove 'synchronized' and instead of using List use CopyOnWriteArrayList. You can find more information here CopyOnWriteArrayList

YuDroid
  • 1,599
  • 5
  • 22
  • 44
  • I've changed the dividedCharList type to the CopyOnWriteArrayList but that didn't resolve the problem. I also removed the synchronized. – Tim Kranen Jan 24 '14 at 12:04
  • Instead of using dividedCharList directly in fillGrids() method, create local copy of it and then use it to set adapter. Have a try for it.. – YuDroid Jan 24 '14 at 12:10
  • Is CharacterGridAdapter your custom adapter class? Can you post code for it? – YuDroid Jan 24 '14 at 12:18
  • Coming right up, but it's nothing special really. A standard adapter that doesn't even modify the views. – Tim Kranen Jan 24 '14 at 12:19
  • You did not change List listChar this to CopyOnWriteArrayList in the constructor as well as private List objects; this to CopyOnWriteArrayList. This should be now same on all instances whenever it has been used.. – YuDroid Jan 24 '14 at 12:27
  • But the Android ArrayAdapter doesn't have a constructor that allows a CopyOnWriteArrayList. It only allows arrays or lists. – Tim Kranen Jan 24 '14 at 12:31
  • Man, I'm talking about this : CharacterGridAdapter aa = new CharacterGridAdapter(this, R.layout.charactergrid_cell, dividedCharList.get(i)); If you are using above constructor, then from where the ArrayAdapter will come into picture..? – YuDroid Jan 24 '14 at 12:33
  • The CharacterGridAdapter extends from the ArrayAdapter – Tim Kranen Jan 25 '14 at 13:54