I'm having a real troubling issue here, I'm encountering a ConcurrentModificationException in the ArrayAdapter.add(Object o) method. Actually the stacktrace points to to the list.size() method in the ArrayAdapter. But it's incredibly unusual since I don't even iterate the list. Here's the code snippet that crashes the code:
private void addCharacterToPager(Character savedChar) {
RelativeLayout lastGrid = pagerAdapter.retrieveViews().get(
pagerAdapter.getCount() - 1);
// get gridview
GridView lastGridView = (GridView) lastGrid.getChildAt(lastGrid
.getChildCount() - 1);
CharacterGridAdapter adapter = (CharacterGridAdapter) lastGridView
.getAdapter();
adapter.add(savedChar);
adapter.notifyDataSetChanged();
pagerAdapter.retrieveViews().set(pagerAdapter.getCount(), lastGrid);
pagerAdapter.notifyDataSetChanged();
}
This is my custom ArrayAdapter:
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, listChar);
this.context = context;
this.resource = resource;
this.objects = listChar;
}
public void updateCollection(List<Character> listChar) {
this.objects = listChar;
}
public List<Character> retrieveCollection() {
return this.objects;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View rowView = convertView;
ImageView charImg = null;
if (rowView == null) {
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
rowView = inflater.inflate(R.layout.charactergrid_cell, null);
charImg = (ImageView) rowView
.findViewById(R.id.characterImage_cell);
} else {
charImg = (ImageView) convertView
.findViewById(R.id.characterImage_cell);
}
Character currentChar = objects.get(position);
if (currentChar.getName().equals("add")
&& currentChar.getGame().equals("add")) {
//set charimg to add icon
charImg.setImageResource(R.drawable.add);
} else {
if(currentChar.getCharacterImage() != null) {
//set charimg to url
Picasso.with(context).load(currentChar.getCharacterImage().getUrl()).into(charImg);
} else {
//set charimg to default
}
}
return rowView;
}
}
This is the stacktrace:
01-29 12:58:12.666: E/AndroidRuntime(18891):at java.util.ConcurrentModificationException
01-29 12:58:12.666: E/AndroidRuntime(18891):at java.util.AbstractList$SubAbstractList.size(AbstractList.java:360)
01-29 12:58:12.666: E/AndroidRuntime(18891):at java.util.AbstractList.add(AbstractList.java:425)
01-29 12:58:12.666: E/AndroidRuntime(18891):at android.widget.ArrayAdapter.add(ArrayAdapter.java:179)
01-29 12:58:12.666: E/AndroidRuntime(18891):at com.xx.playpalproject.ProfileActivity$SaveCharacter.addCharacterToPager(ProfileActivity.java:648)
I really don't get the issue, all I'm trying to do is add an item to the adapter..
Update
I solved the initial issue, I was adding an item to the collection that I set the adapter to before executing the addCharacterToPager method. BUT this didn't solve it at all really. Now I get the exact same error but when trying to modify the pagerAdapter collection and notifying that it's data has changed. So the original problem is still there but it moved it has moved to another adapter..
Update 2
Instead of trying to add an item, I tried to rebuilding the entire ViewPager and to my surprise it ALSO gave me a ConcurrentModificationException. This time it is thrown in the getCount() method of an ArrayAdapter, but I don't know if this is actually my custom adapter. Here's the stacktrace:
01-29 14:26:56.036: E/AndroidRuntime(23898): FATAL EXCEPTION: main
01-29 14:26:56.036: E/AndroidRuntime(23898): java.util.ConcurrentModificationException
01-29 14:26:56.036: E/AndroidRuntime(23898): at java.util.AbstractList$SubAbstractList.size(AbstractList.java:360)
01-29 14:26:56.036: E/AndroidRuntime(23898): at android.widget.ArrayAdapter.getCount(ArrayAdapter.java:330)
01-29 14:26:56.036: E/AndroidRuntime(23898): at android.widget.AbsListView.onAttachedToWindow(AbsListView.java:2642)
01-29 14:26:56.036: E/AndroidRuntime(23898): at android.view.View.dispatchAttachedToWindow(View.java:11983)
01-29 14:26:56.036: E/AndroidRuntime(23898): at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2495)
01-29 14:26:56.036: E/AndroidRuntime(23898): at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2502)
01-29 14:26:56.036: E/AndroidRuntime(23898): at android.view.ViewGroup.addViewInner(ViewGroup.java:3469)
01-29 14:26:56.036: E/AndroidRuntime(23898): at android.view.ViewGroup.addView(ViewGroup.java:3301)
01-29 14:26:56.036: E/AndroidRuntime(23898): at android.support.v4.view.ViewPager.addView(ViewPager.java:1304)
01-29 14:26:56.036: E/AndroidRuntime(23898): at android.view.ViewGroup.addView(ViewGroup.java:3246)
01-29 14:26:56.036: E/AndroidRuntime(23898): at android.view.ViewGroup.addView(ViewGroup.java:3222)
01-29 14:26:56.036: E/AndroidRuntime(23898): at com.timkranen.adapters.CustomPagerAdapter.instantiateItem(CustomPagerAdapter.java:22)
01-29 14:26:56.036: E/AndroidRuntime(23898): at android.support.v4.view.ViewPager.addNewItem(ViewPager.java:832)
01-29 14:26:56.036: E/AndroidRuntime(23898): at android.support.v4.view.ViewPager.populate(ViewPager.java:982)
01-29 14:26:56.036: E/AndroidRuntime(23898): at android.support.v4.view.ViewPager.populate(ViewPager.java:914)
01-29 14:26:56.036: E/AndroidRuntime(23898): at android.support.v4.view.ViewPager.setAdapter(ViewPager.java:442)
01-29 14:26:56.036: E/AndroidRuntime(23898): at com.xx.playpalproject.ProfileActivity.setupCharacterGrid(ProfileActivity.java:175)
01-29 14:26:56.036: E/AndroidRuntime(23898): at com.xx.playpalproject.ProfileActivity.access$8(ProfileActivity.java:166)
01-29 14:26:56.036: E/AndroidRuntime(23898): at com.xx.playpalproject.ProfileActivity$SaveCharacter.done(ProfileActivity.java:638)
The setupCharacterGrid()
method:
private void setupCharacterGrid() {
charPager.setAdapter(null);
List<List<Character>> dividedLists = Lists.partition(currentCharacters,
9);
if (isOwner) {
dividedLists.get(0).add(0, new Character("add", "add"));
}
fillGrids(dividedLists);
pagerAdapter = new CustomPagerAdapter(characterGrids);
charPager.setAdapter(pagerAdapter);
charPager.setPageTransformer(true, new ZoomPagerTransformer());
charPager.setCurrentItem(0);
}
And the fillGrids()
method:
private void fillGrids(List<List<Character>> divList) {
for (List<Character> list : divList) {
RelativeLayout rLayout = new RelativeLayout(this);
GridView gridView = new GridView(this);
gridView.setNumColumns(3);
gridView.setVerticalSpacing(70);
CharacterGridAdapter aa = new CharacterGridAdapter(this,
R.layout.charactergrid_cell, list);
gridView.setAdapter(aa);
gridView.setLayoutParams(genLayoutParams());
gridView.setOnItemClickListener(new GridClick());
rLayout.addView(gridView);
characterGrids.add(rLayout);
}
}
The CustomPagerAdapter:
public class CustomPagerAdapter extends PagerAdapter {
public List<RelativeLayout> gridViews;
public CustomPagerAdapter(List<RelativeLayout> gridViews) {
this.gridViews = gridViews;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
RelativeLayout gridView = gridViews.get(position);
container.addView(gridView);
return gridView;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView(gridViews.get(position));
}
@Override
public int getCount() {
return gridViews.size();
}
@Override
public boolean isViewFromObject(View view, Object o) {
return view == o;
}
public List<RelativeLayout> retrieveViews() {
return gridViews;
}
public void updateCollection(List<RelativeLayout> gridViews) {
this.gridViews = gridViews;
}
}