RecyclerView:检测到不一致。无效的商品位置。原因-使用计时器删除项目

时间:2018-06-26 05:19:49

标签: java android listview android-recyclerview

在继续之前,我在google上搜索了此错误,发现了很多可用的答案,但我的情况与他们的情况不同。

java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position 2(offset:2).state:3

我正在使用recyclerview显示民意测验问题,每个问题都有一个计时器,当计时器用尽时,该项目将从列表中删除。

当计时器用尽时会发生异常,但仅在少数情况下会剩余较少的时间(例如100毫秒)。因此,在这种情况下,可能是recyclerview膨胀了物品,同时计时器耗尽了,recyclerview尝试删除了该物品。

错误是计时器删除项目时出现异常。

因此,当该轮询剩余1秒或更少的时间时,我从数据集中删除了元素后就解决了。因此它将不会在列表中添加项目,这将运行计时器。

  

如果您想产生错误,只需在其中启动倒数计时器   bindView,一旦计时器用尽,请删除该特定项目。   您必须将计时器设置为低于500毫秒。

因此,现在一切正常。解决了在极少数情况下崩溃的问题,但是即使剩余的时间更少,我也不想从数据集中删除该元素。请给我适当的解决方案来解决此错误。

已编辑

java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position 1(offset:1).state:2 com.lsjwzh.widget.recyclerviewpager.RecyclerViewPager{182da0c VFED..... .F....ID 0,0-720,1024 #7f0a01a1 app:id/recycler_view}, adapter:com.lsjwzh.widget.recyclerviewpager.RecyclerViewPagerAdapter@c9403f, layout:android.support.v7.widget.LinearLayoutManager@6fdbd0c, context:com.bitpoll.polls.MainActivity@b40f4c0
     android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5817)
     android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5752)
     android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5748)
     android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2232)
     android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1559)
     android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1519)
     android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:614)
     android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3812)
     android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:3529)
     android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:4082)
     android.view.View.layout(View.java:17969)
     android.view.ViewGroup.layout(ViewGroup.java:5721)
     android.support.v4.widget.SwipeRefreshLayout.onLayout(SwipeRefreshLayout.java:606)
     android.view.View.layout(View.java:17969)
     android.view.ViewGroup.layout(ViewGroup.java:5721)
     android.widget.RelativeLayout.onLayout(RelativeLayout.java:1189)
     android.view.View.layout(View.java:17969)
     android.view.ViewGroup.layout(ViewGroup.java:5721)
     android.support.constraint.ConstraintLayout.onLayout(ConstraintLayout.java:1855)
     android.view.View.layout(View.java:17969)
     android.view.ViewGroup.layout(ViewGroup.java:5721)
     android.support.design.widget.HeaderScrollingViewBehavior.layoutChild(HeaderScrollingViewBehavior.java:132)
     android.support.design.widget.ViewOffsetBehavior.onLayoutChild(ViewOffsetBehavior.java:42)
     android.support.design.widget.AppBarLayout$ScrollingViewBehavior.onLayoutChild(AppBarLayout.java:1361)
     android.support.design.widget.CoordinatorLayout.onLayout(CoordinatorLayout.java:894)
     android.view.View.layout(View.java:17969)
     android.view.ViewGroup.layout(ViewGroup.java:5721)
     android.widget.RelativeLayout.onLayout(RelativeLayout.java:1189)
     android.view.View.layout(View.java:17969)
     android.view.ViewGroup.layout(ViewGroup.java:5721)
     android.widget.FrameLayout.layoutChildren(FrameLayout.java:383)
     android.widget.FrameLayout.onLayout(FrameLayout.java:321)
     android.view.View.layout(View.java:17969)
     android.view.ViewGroup.layout(ViewGroup.java:5721)
     android.widget.LinearLayout.setChildFrame(LinearLayout.java:1982)
     android.widget.LinearLayout.layoutVertical(LinearLayout.java:1826)
     android.widget.LinearLayout.onLayout(LinearLayout.java:1735)
     android.view.View.layout(View.java:17969)
     android.view.ViewGroup.layout(ViewGroup.java:5721)
     android.widget.FrameLayout.layoutChildren(FrameLayout.java:383)
     android.widget.FrameLayout.onLayout(FrameLayout.java:321)
     android.view.View.layout(View.java:17969)
     android.view.ViewGroup.layout(ViewGroup.java:5721)
     android.widget.LinearLayout.setChildFrame(LinearLayout.java:1982)
     android.widget.LinearLayout.layoutVertical(LinearLayout.java:1826)
     android.widget.LinearLayout.onLayout(LinearLayout.java:1735)
     android.view.View.layout(View.java:17969)
     android.view.ViewGroup.layout(ViewGroup.java:5721)
     android.widget.FrameLayout.layoutChildren(FrameLayout.java:383)
     android.widget.FrameLayout.onLayout(FrameLayout.java:321)
     com.android.internal.policy.DecorView.onLayout(DecorView.java:753)
     android.view.View.layout(View.java:17969)

已更新

这是适配器代码。

public class PollAdapter extends RecyclerView.Adapter<PollAdapter.PollViewHolder> {

    // .... 

    @Override
    public void onBindViewHolder(@NonNull PollViewHolder holder, int position) {

    // ...

        if (holder.countDownTimer != null) {
            holder.countDownTimer.cancel();
        }

        // CountDown to set Timer in poll
        holder.countDownTimer = new CountDownTimer(<Timer to be finished.>, 1000) {

            public void onTick(long millisUntilFinished) {
                holder.time.setText("<Remaining time>");
            }

            public void onFinish() {
                removeAt(holder.getAdapterPosition());
            }

        }.start();
    }

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

    // To Remove Poll after Time finished
    public void removeAt(int position) {
    pollList.remove(position);
        notifyItemRemoved(position);
    }
}

8 个答案:

答案 0 :(得分:3)

如果未通知Adapter的{​​{1}}进行更改,则会发生此错误。

要解决此错误,请在基础RecyclerView中查找所有更改数据的点,对此没有直接解决方案,因为这是内部崩溃,由Adapter引发< / p>

您可以做的是:

  1. 自添加以来,添加时调用RecyclerView
  2. 并且由于要删除,因此删除时请致电notifyItemInserted

要对此进行测试而不进行任何优化,您也可以同时调用notifyItemRemoved

答案 1 :(得分:2)

似乎是同时添加和删除项目的情况。我认为可以通过顺序执行所有任务来解决。由于您的代码彼此不相关,因此建议您使用recycler.post(new Runnable(){});并将您的代码放入run方法中,添加/删除元素,然后notifyDatasetChanged()应该在此run方法中完成。让我知道结果

答案 2 :(得分:1)

@Moinkhan尝试在onBindViewHolder中添加holder.setIsRecyclable(false)

答案 3 :(得分:1)

使用自定义LinearLayoutManager

public class CustLinearLayoutManager extends LinearLayoutManager {

public CustLinearLayoutManager(Context context) {
    super(context);
}

public CustLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
    super(context, orientation, reverseLayout);
}

public CustLinearLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    super(context, attrs, defStyleAttr, defStyleRes);
}

// Something is happening here

@Override
public boolean supportsPredictiveItemAnimations() {
    return false;
  }
}

使用:-

CustLinearLayoutManager clm = new CustLinearLayoutManagerr(mContext);
recyclerView.setLayoutManager(clm);

我希望它能起作用

答案 4 :(得分:0)

此问题主要是由于职位问题引起的。

如果您删除某个位置或进行任何更改,则请调用notifydatasetchanged,那么只会进行更改。

如果您删除某个位置,或者如果未调用notydatasetchanged而不是清除一个数组,则只需清除一个数组,那么recyclerview会将这些位置保持初始状态。

如果有一个数据数组,我只是清除了数组,然后尝试滚动recyclerview,将显示此问题,因为notydatasetchanged未调用。 (回收者视图中有位置,但找不到数组正子)

NB:对不起,我的英语不好

答案 5 :(得分:0)

我有类似的问题。我有5台设备,而我仅在一台设备( lenovo-k6 ,牛轧糖7.0)中遇到错误。它正在其他牛轧糖手机中运行。这是设备特定的错误

从活动A>活动B导航时, 活动A的onDestroy()被调用了。 在onDestroy()中,我正在清除我的静态数组列表。[仅在 lenovo-k6 ,牛轧糖7.0中发生过

由于我通知适配器的空列表,我在活动B的recyclerView上出现OnScrolling错误。

希望它可以帮助某人。

答案 6 :(得分:0)

问题可能与适配器有关。如果在适配器构造函数中使用setHasStableIds(true);,则需要确保使用stable ids

确保在适配器中正确覆盖getItemId。 应该是:

@Override
public long getItemId(int position) {
   return yourList == null ? 0 : yourList.get(position).getId();
}

不是

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

答案 7 :(得分:0)

我遇到此错误是因为在设置recyclerview和适配器时,我放弃了删除这一行代码:

mRecyclerView.setHasFixedSize(true);

您不能具有固定的大小,不能删除或添加或具有可过滤的recycleview(带有搜索)。在代码中检查该行。