填充RecyclerView当ArrayIndexOutOfBoundsException异常 [英] ArrayIndexOutOfBoundsException when populating RecyclerView

查看:2372
本文介绍了填充RecyclerView当ArrayIndexOutOfBoundsException异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我得到一个错误,每隔一段时间当我尝试填充我RecyclerView但错误似乎在内部发生的 StaggeredGridLayoutManager

我填充从我的数据库中的RecyclerView然后使用这个图像添加到我的适配器

 列表< WImage>图像;公共无效addImages(LinkedHashMap的<整数,WImage> newImages){
    对于(Map.Entry的<整数,WImage>项:newImages.entrySet()){
        addImage(entry.getValue(),entry.getKey());
    }
}公共无效addImage(WImage形象,诠释位置){
    images.add(位置,图像);
    notifyItemRangeInserted(位置,1);}

什么是奇怪的是,当应用程序第一次加载它是好的,正确地显示一切,但如果我有一组不同的基于数据库查询图像替换一下目前正处于RecyclerView然后用初始图像再次,我得到回来这个错误。

  java.lang.ArrayIndexOutOfBoundsException:src.length = 16 srcPos = 0 dst.length = 0 dstPos = 0长度= 16
            在java.lang.System.arraycopy(本机方法)
            在android.support.v7.widget.StaggeredGridLayoutManager$LazySpanLookup.ensureSize(StaggeredGridLayoutManager.java:2277)
            在android.support.v7.widget.StaggeredGridLayoutManager$LazySpanLookup.offsetForAddition(StaggeredGridLayoutManager.java:2323)
            在android.support.v7.widget.StaggeredGridLayoutManager.handleUpdate(StaggeredGridLayoutManager.java:1280)
            在android.support.v7.widget.StaggeredGridLayoutManager.onItemsAdded(StaggeredGridLayoutManager.java:1253)
            在android.support.v7.widget.RecyclerView $ 5.dispatchUpdate(RecyclerView.java:406)
            在android.support.v7.widget.RecyclerView $ 5.onDispatchSecondPass(RecyclerView.java:422)
            在android.support.v7.widget.AdapterHelper.consumePostponedUpdates(AdapterHelper.java:119)
            在android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:1896)
            在android.support.v7.widget.RecyclerView.resumeRequestLayout(RecyclerView.java:1101)
            在android.support.v7.widget.RecyclerView $ 1.run(RecyclerView.java:155)
            在android.view.Choreographer $ CallbackRecord.run(Choreographer.java:761)
            在android.view.Choreographer.doCallbacks(Choreographer.java:574)
            在android.view.Choreographer.doFrame(Choreographer.java:543)
            在android.view.Choreographer $ FrameDisplayEventReceiver.run(Choreographer.java:747)
            在android.os.Handler.handleCallback(Handler.java:733)
            在android.os.Handler.dispatchMessage(Handler.java:95)
            在android.os.Looper.loop(Looper.java:136)
            在android.app.ActivityThread.main(ActivityThread.java:5086)
            在java.lang.reflect.Method.invokeNative(本机方法)
            在java.lang.reflect.Method.invoke(Method.java:515)
            在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:785)
            在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
            在dalvik.system.NativeStart.main(本机方法)

它遍历所有图片就好了,但是当它准备打电话 onBindViewHolder 再次崩溃。

当我更改RecyclerView数据我从查询中使用新的数据填充之前删除一切先用这种

 公共无效的removeAll(){
    images.clear();
    notifyDataSetChanged();
}

我也试过将它们插入全部一次,然后调用 notifyItemRangeInserted 的起始位置和图像的总数目,但它仍然具有相同的错误crashsed。

修改

这似乎发生时,我打20左右的项目,我需要投入电网。如果我只是用 notifyDatasetChanged 它似乎工作正常,但我想用 notifyItemRangeInserted ,所以我得到了很好的插入动画

有其他人看到这个问题?

EDIT2

这是我的 onCreateViewHolder

  @覆盖
公共ViewHolder onCreateViewHolder(ViewGroup中ViewGroup中,最终int i)以{    视图V = LayoutInflater.from(viewGroup.getContext())膨胀(R.layout.image_normal_grid_cell,ViewGroup中,假的)。
    返回新ViewHolder(V);
}

和我的 onBindViewHolder

  @覆盖
公共无效onBindViewHolder(最终ViewHolder持有人,最终int i)以{
    最终WImage图像= images.get(I)
    holder.v.setOnClickListener(新View.OnClickListener(){
        @覆盖
        公共无效的onClick(视图v){
            listener.onItemClick(V,I,图像);
        }
    });    holder.heart.setActivated(image.getLikeDislike());    holder.heart.setOnClickListener(新View.OnClickListener(){
        @覆盖
        公共无效的onClick(视图v){
            Uri.Builder UB = SyncProvider.CONTENT_ID_URI_BASE.buildUpon();
            ub.appendPath(将String.valueOf(image.getId()));
            ContentValues​​值=新ContentValues​​();            如果(image.getLikeDislike()){
                values​​.put(SyncProvider.LIKE,0);
                holder.heart.setActivated(假);
                image.setLikeDislike(假);
            }其他{
                values​​.put(SyncProvider.LIKE,1);
                holder.heart.setActivated(真);
                image.setLikeDislike(真);
            }
            values​​.put(SyncProvider.IMAGE_CHANGED,1);
            context.getContentResolver()更新(ub.build(),价值观,NULL,NULL);
        }
    });
    如果(cancelPotentialDownload(image.getUri(),holder.imageview)){
        LoadImageTask任务=新LoadImageTask(holder.imageview,image.getThumbUri());
        holder.imageview.setImageDrawable(新AsyncBitmap(任务));
        task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
    }
}

编辑3

在这里,当我更换适配器我做什么

在我的抽屉里资产净值选定的指数变化我初始化我的装载机进行查询

 公共无效initLoader(INT页){
    如果(当前是=页面和放大器;!&安培;!mAdapter = NULL){
        mAdapter.removeAll();
        hashImages.clear();
        。getLoaderManager()destroyLoader(当前页);
    }
    当前页=页;
    。getLoaderManager()initLoader(页,空,这一点);
}

然后在我的onLoadFinished我的装载机我的对象添加到适配器

  @覆盖
公共无效onLoadFinished(装载机<&光标GT; cursorLoader,光标光标){
    如果(光标=空&放大器;!&放大器; cursor.moveToFirst()){
            做{
                WImage形象=新WImage(光标);
                如果(!hashImages.containsKey(image.getId())){
                    newImages.put(tempHash.size(),图像);
                }否则如果(image.getImageChanged()){
                    更新= TRUE;
                }
                INT POS = tempHash.size();
                tempHash.put(image.getId(),POS)
            }而(cursor.moveToNext());
        }    如果(newImages.size()大于0){
            mAdapter.addImages(newImages);
        }


解决方案

我觉得这个问题是由的 HTTPS://$c$c.google.com/p/android/issues/detail ID = 77846
您可以替换 notifyDataSetChanged 调用特定事件通知( notifyItemRemoved /添加),看看是否可以重现吗?

I am getting an error every so often when I try to populate my RecyclerView but the error seems to happening internally in the StaggeredGridLayoutManager.

I populate the RecyclerView from my database then add the images to my adapter using this

List<WImage> images;

public void addImages(LinkedHashMap<Integer,WImage> newImages){
    for(Map.Entry<Integer,WImage> entry : newImages.entrySet()){
        addImage(entry.getValue(),entry.getKey());
    }
}

public void addImage(WImage image, int position){
    images.add(position,image);
    notifyItemRangeInserted(position, 1);

}

What is weird is when the app first loads it is fine and displays everything correctly but if I replace what was currently in the RecyclerView with a different set of images based on a database query then come back with the initial images again I get this error.

java.lang.ArrayIndexOutOfBoundsException: src.length=16 srcPos=0 dst.length=0 dstPos=0 length=16
            at java.lang.System.arraycopy(Native Method)
            at android.support.v7.widget.StaggeredGridLayoutManager$LazySpanLookup.ensureSize(StaggeredGridLayoutManager.java:2277)
            at android.support.v7.widget.StaggeredGridLayoutManager$LazySpanLookup.offsetForAddition(StaggeredGridLayoutManager.java:2323)
            at android.support.v7.widget.StaggeredGridLayoutManager.handleUpdate(StaggeredGridLayoutManager.java:1280)
            at android.support.v7.widget.StaggeredGridLayoutManager.onItemsAdded(StaggeredGridLayoutManager.java:1253)
            at android.support.v7.widget.RecyclerView$5.dispatchUpdate(RecyclerView.java:406)
            at android.support.v7.widget.RecyclerView$5.onDispatchSecondPass(RecyclerView.java:422)
            at android.support.v7.widget.AdapterHelper.consumePostponedUpdates(AdapterHelper.java:119)
            at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:1896)
            at android.support.v7.widget.RecyclerView.resumeRequestLayout(RecyclerView.java:1101)
            at android.support.v7.widget.RecyclerView$1.run(RecyclerView.java:155)
            at android.view.Choreographer$CallbackRecord.run(Choreographer.java:761)
            at android.view.Choreographer.doCallbacks(Choreographer.java:574)
            at android.view.Choreographer.doFrame(Choreographer.java:543)
            at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:747)
            at android.os.Handler.handleCallback(Handler.java:733)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5086)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
            at dalvik.system.NativeStart.main(Native Method)

it goes through all the images just fine but when its ready to call onBindViewHolder again it crashes.

When I change the data in the RecyclerView I remove everything first with this before populating with the new data from the query

public void removeAll(){
    images.clear();
    notifyDataSetChanged();
}

I also tried inserting them all at once and then calling notifyItemRangeInserted with the start position and the total number of images but it still crashsed with the same error.

EDIT

it seems to happen when I hit about 20 or so items that I need to put into the Grid. If I just use notifyDatasetChanged it seems to work fine but I want to use notifyItemRangeInserted so I get the nice insert animation

Has anyone else seen this problem?

EDIT2

here is my onCreateViewHolder

@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, final int i) {

    View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.image_normal_grid_cell, viewGroup, false);
    return new ViewHolder(v);
}

and my onBindViewHolder

@Override
public void onBindViewHolder(final ViewHolder holder, final int i) {
    final WImage image = images.get(i);
    holder.v.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            listener.onItemClick(v,i,image);
        }
    });

    holder.heart.setActivated(image.getLikeDislike());

    holder.heart.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Uri.Builder ub = SyncProvider.CONTENT_ID_URI_BASE.buildUpon();
            ub.appendPath(String.valueOf(image.getId()));
            ContentValues values = new ContentValues();

            if(image.getLikeDislike()){
                values.put(SyncProvider.LIKE,0);
                holder.heart.setActivated(false);
                image.setLikeDislike(false);
            }else{
                values.put(SyncProvider.LIKE,1);
                holder.heart.setActivated(true);
                image.setLikeDislike(true);
            }
            values.put(SyncProvider.IMAGE_CHANGED,1);
            context.getContentResolver().update(ub.build(),values,null,null);
        }
    });
    if(cancelPotentialDownload(image.getUri(),holder.imageview)){
        LoadImageTask task = new LoadImageTask(holder.imageview,image.getThumbUri());
        holder.imageview.setImageDrawable(new AsyncBitmap(task));
        task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
    }
}

EDIT 3

here is what I do when I replace the adapter

on selected index change of my nav drawer I init my loader to make a query

public void initLoader(int page){
    if(currentPage != page && mAdapter != null){
        mAdapter.removeAll();
        hashImages.clear();
        getLoaderManager().destroyLoader(currentPage);
    }
    currentPage = page;
    getLoaderManager().initLoader(page,null,this);
}

then in my onLoadFinished of my loader I add the objects to the adapter

@Override
public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) {
    if(cursor != null && cursor.moveToFirst()){
            do{
                WImage image = new WImage(cursor);
                if(!hashImages.containsKey(image.getId())){
                    newImages.put(tempHash.size(),image);
                }else if(image.getImageChanged()){
                    update = true;
                }
                int pos = tempHash.size();
                tempHash.put(image.getId(),pos);
            }while(cursor.moveToNext());
        }

    if(newImages.size() > 0){
            mAdapter.addImages(newImages);
        }

解决方案

I think this problem is triggered by https://code.google.com/p/android/issues/detail?id=77846. Can you replace notifyDataSetChanged calls with specific notify events (notifyItemRemoved/Added) and see if you can reproduce it?

这篇关于填充RecyclerView当ArrayIndexOutOfBoundsException异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆