本文介绍了在 RecyclerView 中检测到不一致,如何在滚动时更改 RecyclerView 的内容的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 RecyclerView 来显示项目的名称.我的行包含单个 TextView.项目名称存储在 List 中.mItemList.

I'm using RecyclerView to display name of the items. My row contains single TextView. Item names are stored in List<String> mItemList.

要更改RecyclerView 的内容,我替换mItemList 中的Strings 并在RecyclerViewAdapter 上调用notifyDataSetChanged().

To change contents of RecyclerView, I replace Strings in mItemList and call notifyDataSetChanged() on RecyclerViewAdapter.

但是如果我在 RecyclerView 滚动时尝试更改 mItemList 的内容,有时它会给我java.lang.IndexOutOfBoundsException:检测到不一致.无效的项目位置 157(offset:157).state:588

But If I try to change contents of the mItemList while RecyclerView is scrolling, sometimes it gives me java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position 157(offset:157).state:588

如果 mItemList 的大小比以前小,就会发生这种情况.那么更改 RecyclerView 内容的正确方法是什么?这是 RecyclerView 中的错误吗?

This happens if size of mItemList is less than before. So what is the correct way to change contents of the RecyclerView ? Is this a bug in RecyclerView ?

这是异常的完整堆栈跟踪:

Here's full stack trace of Exception:

java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position 157(offset:157).state:588
        at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:3300)
        at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:3258)
        at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:1803)
        at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1302)
        at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1265)
        at android.support.v7.widget.LinearLayoutManager.scrollBy(LinearLayoutManager.java:1093)
        at android.support.v7.widget.LinearLayoutManager.scrollVerticallyBy(LinearLayoutManager.java:956)
        at android.support.v7.widget.RecyclerView$ViewFlinger.run(RecyclerView.java:2715)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:725)
        at android.view.Choreographer.doCallbacks(Choreographer.java:555)
        at android.view.Choreographer.doFrame(Choreographer.java:524)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:711)
        at android.os.Handler.handleCallback(Handler.java:615)
        at android.os.Handler.dispatchMessage(Handler.java:92)
        at android.os.Looper.loop(Looper.java:137)
        at android.app.ActivityThread.main(ActivityThread.java:4921)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:511)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1027)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:794)
        at dalvik.system.NativeStart.main(Native Method)

AdapterView 代码:

AdapterView code:

private static class FileListAdapter extends RecyclerView.Adapter<FileHolder> {
    private final Context mContext;
    private final SparseBooleanArray mSelectedArray;
    private final List<String> mList;

    FileListAdapter(Context context, List<String> list, SparseBooleanArray selectedArray) {
        mList = list;
        mContext = context;
        mSelectedArray = selectedArray;
    }


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

        View view = LayoutInflater.from(viewGroup.getContext()).inflate(
                R.layout.file_list_item, viewGroup, false);

        TextView tv = (TextView) view
                .findViewById(R.id.file_name_text);
        Typeface font = Typeface.createFromAsset(viewGroup.getContext().getAssets(),
                viewGroup.getContext().getString(R.string.roboto_regular));
        tv.setTypeface(font);

        return new FileHolder(view, tv);
    }

    @Override
    public void onBindViewHolder(FileHolder fileHolder, final int i) {

        String name = mList.get(i);

        // highlight view if selected
        setSelected(fileHolder.itemView, mSelectedArray.get(i));

        // Set text
        fileHolder.mTextView.setText(name);
    }

    @Override
    public int getItemCount() {
        return mList.size();
    }
}

private static class FileHolder extends RecyclerView.ViewHolder {

    public final TextView mTextView;

    public FileHolder(View itemView, TextView tv) {
        super(itemView);
        mTextView = tv;
    }
}

推荐答案

该错误现已修复,如果您仍然遇到相同的异常,请确保您正在更新您的适配器数据源仅来自主线程并在其后调用适当的适配器通知方法.

The bug is fixed now, if you're still getting the same Exception, please make sure you're updating your Adapter data source only from the main thread and calling appropriate adapter notify method after it.

旧答案:这似乎是 RecyclerView 中的一个错误,据报道 此处此处.希望它会在下一个版本中修复.

Old answer: It seems to be a bug in RecyclerView, it's reported here and here. Hopefully it will be fixed in the next release.

这篇关于在 RecyclerView 中检测到不一致,如何在滚动时更改 RecyclerView 的内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-03 01:56