Android GridView正在稍后的索引中加载0索引项';数据集更改时的插槽

Android GridView正在稍后的索引中加载0索引项';数据集更改时的插槽,android,android-gridview,Android,Android Gridview,使用带有扩展BaseAdapter的GridView,我正在加载包含图像和标题的RelativeLayouts集合。当用户在GridView中单击其中一个项目时,应将其从网格中删除并替换为其后面的项目 这适用于除第一个之外的任何项目(适配器管理的项目的ArrayList中的索引0) 在我正在测试的设备上,当屏幕完全滚动到网格顶部(3列4行),最后一行稍微被切断时,屏幕能够显示12个项目。第五排根本没有显示。在这种情况下,如果单击第一个项目(将其删除),所有项目都将正确填写,但是,第5行的第一个项

使用带有扩展BaseAdapter的GridView,我正在加载包含图像和标题的RelativeLayouts集合。当用户在GridView中单击其中一个项目时,应将其从网格中删除并替换为其后面的项目

这适用于除第一个之外的任何项目(适配器管理的项目的ArrayList中的索引0)

在我正在测试的设备上,当屏幕完全滚动到网格顶部(3列4行),最后一行稍微被切断时,屏幕能够显示12个项目。第五排根本没有显示。在这种情况下,如果单击第一个项目(将其删除),所有项目都将正确填写,但是,第5行的第一个项目(索引12)返回第一个项目(索引0)的视图,而不是索引12处的项目

一些屏幕有助于解释问题:

点击布莱恩·麦克奈特(Brian McKnight)将删除他,贝克和其他人将填补空缺

贝克和其他人一起填写了表格,现在向下滚动到下一行

哦。贝克也在那里。我让它部分滚动,以便您可以看到这两个项目都有贝克图片

向上滚动以使项目12(第5行)不可见,然后向下滚动可更正问题

public class PopularArtistsGridAdapter extends BaseAdapter {

    private ArrayList<ArtistsListItem> mArtists = new ArrayList<ArtistsListItem>();
    private LayoutInflater mInflater;
    private Context mContext;

    private int mRemovedIndex = -1;
    private int mRefresher = -1;
    private int mLastVisible = -1;

    public PopularArtistsGridAdapter(Context context) {
        mContext = context;
        mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    public void setItems(ArrayList<ArtistsListItem> artists) {
        if(artists == null)
            throw new NullPointerException();

        mArtists = artists;
        notifyDataSetChanged();
    }

    @Override
    public int getCount() {
        return mArtists.size();
    }

    public void removeItem(int position, int lastVisible) {
        mLastVisible = lastVisible;

        mRemovedIndex = position;
        mRefresher = mRemovedIndex;

        mArtists.remove(position);
        notifyDataSetChanged();
    }

    public void addItem(int position) {
        ArtistsListItem item = getItem(position);

        mArtists.add(0, item);
        notifyDataSetChanged();
    }

    @Override
    public ArtistsListItem getItem(int position) {
        return mArtists.get(position);
    }

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

    private void iterateRefresher() {
        mRefresher++;

        if(mRefresher > mLastVisible) {
            mRemovedIndex = -1;
            mRefresher = -1;
            mLastVisible = -1;
        }
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {

        final ArtistsListItem item = getItem(position);

        if(convertView == null)
            convertView = mInflater.inflate(R.layout.popular_artist_item, null);

        final TextView tv = (TextView) convertView.findViewById(R.id.pai_stupid_bubble_button);
        final ImageView iv = (ImageView) convertView.findViewById(R.id.pai_image);

        final BitmapDrawable drawable = DrawableManager.fetchBitmapDrawable(mContext, item.getImageURL(), true, false);

        iv.invalidate();
        tv.invalidate();

        if(mRefresher >= 0 && position >= mRefresher) {
            Animation anim = AnimationUtils.loadAnimation(mContext, R.anim.grid_item_fadein);
            anim.setAnimationListener(new AnimationListener() {

                @Override
                public void onAnimationStart(Animation animation) {
                    iv.setImageDrawable(drawable);
                    tv.setText(item.getName());
                }

                @Override
                public void onAnimationRepeat(Animation animation) {
                    // TODO Auto-generated method stub

                }

                @Override
                public void onAnimationEnd(Animation animation) {
                    // TODO Auto-generated method stub

                }
            });

            anim.setStartOffset(300 + (50 * (position - mRemovedIndex)));

            convertView.startAnimation(anim);
            iterateRefresher();
        }
        else {
            iv.setImageDrawable(drawable);
            tv.setText(item.getName());
        }

        return convertView;
    }

}
网格中任何其他项的此过程都正常工作,只有项0。我做了一些记录,发现了一些东西:

  • 对象0的getView(…)方法调用很多。当网格第一次加载时,将调用3次,而所有其他项仅调用一次
  • 删除项目0以外的项目时,将调用位置0的getView(…)19次。3,然后在调用其他对象的所有getView(…)方法之后再调用16次
  • 删除项目0时,向下滚动到第5行(项目12)后,将调用0的getView(…)方法两次。我认为这就是问题发生的地方,因为有时如果你能看到正确的项目在被项目@position 0覆盖之前开始加载
因此,我非常确定,当出现@index 12项时,对位置0额外调用了2次getView(…),这是导致此问题的原因。我不知道的是为什么会在那时调用位置0的getView(…),以及为什么它会决定覆盖@position 12的项

我将在下面包含适配器的代码,我认为这足以解决问题

public class PopularArtistsGridAdapter extends BaseAdapter {

    private ArrayList<ArtistsListItem> mArtists = new ArrayList<ArtistsListItem>();
    private LayoutInflater mInflater;
    private Context mContext;

    private int mRemovedIndex = -1;
    private int mRefresher = -1;
    private int mLastVisible = -1;

    public PopularArtistsGridAdapter(Context context) {
        mContext = context;
        mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    public void setItems(ArrayList<ArtistsListItem> artists) {
        if(artists == null)
            throw new NullPointerException();

        mArtists = artists;
        notifyDataSetChanged();
    }

    @Override
    public int getCount() {
        return mArtists.size();
    }

    public void removeItem(int position, int lastVisible) {
        mLastVisible = lastVisible;

        mRemovedIndex = position;
        mRefresher = mRemovedIndex;

        mArtists.remove(position);
        notifyDataSetChanged();
    }

    public void addItem(int position) {
        ArtistsListItem item = getItem(position);

        mArtists.add(0, item);
        notifyDataSetChanged();
    }

    @Override
    public ArtistsListItem getItem(int position) {
        return mArtists.get(position);
    }

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

    private void iterateRefresher() {
        mRefresher++;

        if(mRefresher > mLastVisible) {
            mRemovedIndex = -1;
            mRefresher = -1;
            mLastVisible = -1;
        }
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {

        final ArtistsListItem item = getItem(position);

        if(convertView == null)
            convertView = mInflater.inflate(R.layout.popular_artist_item, null);

        final TextView tv = (TextView) convertView.findViewById(R.id.pai_stupid_bubble_button);
        final ImageView iv = (ImageView) convertView.findViewById(R.id.pai_image);

        final BitmapDrawable drawable = DrawableManager.fetchBitmapDrawable(mContext, item.getImageURL(), true, false);

        iv.invalidate();
        tv.invalidate();

        if(mRefresher >= 0 && position >= mRefresher) {
            Animation anim = AnimationUtils.loadAnimation(mContext, R.anim.grid_item_fadein);
            anim.setAnimationListener(new AnimationListener() {

                @Override
                public void onAnimationStart(Animation animation) {
                    iv.setImageDrawable(drawable);
                    tv.setText(item.getName());
                }

                @Override
                public void onAnimationRepeat(Animation animation) {
                    // TODO Auto-generated method stub

                }

                @Override
                public void onAnimationEnd(Animation animation) {
                    // TODO Auto-generated method stub

                }
            });

            anim.setStartOffset(300 + (50 * (position - mRemovedIndex)));

            convertView.startAnimation(anim);
            iterateRefresher();
        }
        else {
            iv.setImageDrawable(drawable);
            tv.setText(item.getName());
        }

        return convertView;
    }

}
公共类PopularTistsGridAdapter扩展了BaseAdapter{
private ArrayList mArtists=new ArrayList();
私人停车场;
私有上下文;
私有int mRemovedIndex=-1;
private int mRefresher=-1;
private int mLastVisible=-1;
公共PopularTistsGridAdapter(上下文){
mContext=上下文;
mInflater=(LayoutInflater)context.getSystemService(context.LAYOUT\u充气机\u服务);
}
公共无效集合项(ArrayList艺术家){
如果(艺术家==null)
抛出新的NullPointerException();
火星人=艺术家;
notifyDataSetChanged();
}
@凌驾
public int getCount(){
返回mArtists.size();
}
public void removietem(int position,int lastVisible){
mLastVisible=lastVisible;
mRemovedIndex=位置;
mRefresher=mRemovedIndex;
移除(位置);
notifyDataSetChanged();
}
公共无效附加项(内部位置){
ArtistsListItem=getItem(位置);
添加(0,项目);
notifyDataSetChanged();
}
@凌驾
公共艺术人员StitItem getItem(内部位置){
返回火星人。获取(位置);
}
@凌驾
公共长getItemId(int位置){
返回位置;
}
私有void迭代器刷新器(){
mRefresher++;
如果(mRefresher>mLastVisible){
mRemovedIndex=-1;
mRefresher=-1;
mLastVisible=-1;
}
}
@凌驾
公共视图getView(最终整数位置、视图转换视图、视图组父视图){
最终艺人项目=获取项目(位置);
if(convertView==null)
convertView=mInflater.inflate(R.layout.popular\u艺术家项目,空);
最终文本视图tv=(文本视图)convertView.findViewById(R.id.pai\u dumble\u bubble\u按钮);
最终ImageView iv=(ImageView)convertView.findViewById(R.id.pai_图像);
final BitmapDrawable drawable=DrawableManager.fetchBitmapDrawable(mContext,item.getImageURL(),true,false);
iv.使无效();
tv.invalidate();
如果(mRefresher>=0&&position>=mRefresher){
动画动画=AnimationUtils.loadAnimation(mContext,R.anim.grid\u item\u fadein);
anim.setAnimationListener(新的AnimationListener(){
@凌驾
onAnimationStart上的公共无效(动画){
iv.设置图像可绘制(可绘制);
tv.setText(item.getName());
}
@凌驾
onAnimationRepeat上的公共无效(动画){
//TODO自动生成的方法存根
}
@凌驾
onAnimationEnd上的公共无效(动画){
//TODO自动生成的方法存根
}
});
动画设置开始偏移量(300+(50*(位置-mRemovedIndex));
convertView.startAnimation(动画);
迭代器刷新器();
}
否则{
iv.设置图像可绘制(可绘制);
tv.setText(item.getName());
}
返回视图;
}
}
我制作了一个刷新器,在替换移除的项目时,允许屏幕上所有可见的项目淡入。如果有人
class MyAnimationListener extends AnimationListener {
    private int positionToMutate;

    public MyAnimationListener(int positionToMutate) {
        this.positionToMutate = positionToMutate;
    }

    @Override
    public void onAnimationStart(Animation animation) {
        Integer viewPosition = (Integer)localConvertView.getTag(); // add this to getView as final View localConvertView
        if (positionToMutate == viewPosition) {
            iv.setImageDrawable(drawable);
            tv.setText(item.getName());
        }
    }
    // rest of the methods
}
final View localConvertView = convertView;
localConvertView.setTag(new Integer(position));