ArrayAdapter中的ConcurrentModificationException添加方法

时间:2014-01-29 12:02:19

标签: java android concurrentmodification

我在这里遇到了一个真正令人不安的问题,我在ArrayAdapter.add(Object o)方法中遇到了ConcurrentModificationException。实际上,stacktrace指向ArrayAdapter中的list.size()方法。但这是非常不寻常的,因为我甚至没有迭代列表。这是崩溃代码的代码片段:

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();

    }

这是我的自定义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;
}

}

这是堆栈跟踪:

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)

我真的没有得到这个问题,我所要做的就是在适配器上添加一个项目..

更新

我解决了最初的问题,我在向执行addCharacterToPager方法之前设置适配器的集合中添加了一个项目。 但是这根本没有解决它。现在我得到完全相同的错误但是在尝试修改pagerAdapter集合并通知它的数据已经改变时。所以最初的问题仍然存在,但它已经移动到另一个适配器..

更新2

我没有尝试添加项目,而是尝试重建整个ViewPager,令我惊讶的是它也给了我一个ConcurrentModificationException。这次是在ArrayAdapter的getCount()方法中抛出,但我不知道这是否实际上是我的自定义适配器。这是堆栈跟踪:

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)

setupCharacterGrid()方法:

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);
}

fillGrids()方法:

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);
    }
}

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;
}

}

1 个答案:

答案 0 :(得分:0)

我认为错误在于您的instantiatItem()方法。无论我见过什么实现,这种方法似乎都是为了创建一个新对象,而不是引用一个现有对象。您需要使用新的 inflater.inflate ,并将此视图添加到container视图组。

你使用它的方式似乎getCount()期望的元素数量与它提供的元素数量不同,如果你只是引用一个对象而不是像我上面写的那样创建它就会有意义,并得出结论它正在被几种方法修改。尝试创建一个新实例,它应该可以工作。