Android RecyclerView,项目扫描,java.lang.IllegalStateException

Android RecyclerView,项目扫描,java.lang.IllegalStateException,android,android-recyclerview,Android,Android Recyclerview,我的任务是在RecyclerView中实现项目水平项目滑动。多亏了ViewPager源代码和其他一些资源,我实际上已经完成了这项任务,但有一个场景存在问题 我的SwipeableRecyclerView(从现在起SRV)扩展了RecyclerView,并实现了RecyclerView.OnItemTouchListener来执行这个神奇的功能,它实际上是有效的。它还定义了一个自定义接口SwipeListener,它定义了一些方法,最重要的(对于这个问题)是“onSwipe(视图、int位置、布尔

我的任务是在RecyclerView中实现项目水平项目滑动。多亏了ViewPager源代码和其他一些资源,我实际上已经完成了这项任务,但有一个场景存在问题

我的SwipeableRecyclerView(从现在起SRV)扩展了RecyclerView,并实现了RecyclerView.OnItemTouchListener来执行这个神奇的功能,它实际上是有效的。它还定义了一个自定义接口SwipeListener,它定义了一些方法,最重要的(对于这个问题)是“onSwipe(视图、int位置、布尔右)”

“我的活动”向SRV提供接口的实现,当检测到刷卡并触发侦听器方法时,它会执行以下操作:

  • 使用“view.animate().translationX(translationX)”以正确的方向将项目/滑动视图移出屏幕
  • 上面启动的动画有一个侦听器,在onAnimationEnd中,该侦听器从适配器中删除指定位置的项,并调用Adapter.notifyItemRemoved(position)
  • 其结果是,视图消失到滑动的一侧,然后回收者用其动画移除该行-所有这些实际上都非常好
当我快速滑动时,有时会出现问题,例如在第一个动画尚未完成时,我开始滑动另一行。有时,它会在没有视图的情况下创建“洞”或幻影行;有时,我会遇到以下例外情况:

java.lang.IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling
堆栈跟踪显示adapter.notifyItemRemoved()是导致异常的方法

对于异常问题,事件顺序如下(从我的调试跟踪):

因此,两个完成动画都是一个接一个地开始的,当其中一个删除了它的项并调用notifyItemRemoved时,另一个完成了并调用了removing该项。我真的不确定这是怎么回事,因为所有这些都发生在主线程上,但我猜滚动也在动画帧中完成,而且由于第二次删除,它以某种方式需要新的计算

所以,我陷入困境,我不知道该怎么办。实际上,我认为最简单的事情应该是在动画启动时禁用整个recycler视图的触摸,并且只有在滚动完成后才再次启用它们。我无法禁用SRV,虽然-我尝试了setEnabled(false)、clickable等,但没有任何效果


有什么帮助吗?

以下是最终对我有效的方法:

  • 将swipingEnabled属性添加到SRV;如果为false,onInterceptTouchEvent只会调用父实现,从而有效地禁用项扫描
  • 在负责处理刷卡手势的方法中添加此代码(如删除条目等):

  • 在创建SRV的位置附近添加以下代码:

    swipeableRecyclerView.setItemAnimator(new DefaultItemAnimator() {
    
        @Override
        public void onRemoveFinished(RecyclerView.ViewHolder item) {
            swipeableRecyclerView.setSwipingEnabled(true);
        }
    });
    
    这只是使用一个方法的实现扩展了默认项animator,该方法在删除动画完成时调用


现在,我的刷消是“序列化”的,没有异常发生。

您可以检查
mRecyclerView.getItemAnimator().isRunning()
,这比当前答案要简单一些。虽然
true
MotionEvent
s不应触发任何删除操作。

我测试了这个,但它不起作用。我仍然能够滑动两个或多个视图,使它们的动画重叠,这导致崩溃。同意,我的代码的其余部分可能有错误,我将进行更多的测试。谢谢你的帖子,虽然,我不知道你提到的方法,它的妹妹需要一个听众-很酷的东西。动画似乎是由adapter.notifyItemRemoved()触发的。我理解为什么它对我不起作用:当我检测到解雇时,在我的解决方案(代理标志)中,我立即禁用任何其他滑动并启动完成动画,其onAnimationEnd侦听器方法将删除该项并调用notifyItemRemoved(),使“删除”动画开始。您提出的解决方案引入了一个非常短的窗口(从我的滑动完成动画开始运行到调用notifyItemRemoved()方法开始动画)。(在另一条评论中继续)。时间窗口很短,但我仍然能够在调用第一个项目的notifyItemRemoved()之前开始滑动第二个项目,这会产生问题。在我的解决方案中,由于我在检测到滑动手势后立即禁用滑动,因此在动画运行时用户不可能再次滑动。这很棘手。我认为这两个条件都是必要的。只要上一个滑动动作正在进行,您就不应该听新的滑动动作,只要移除动画处于打开状态,即,您就不应该听新的滑动动作。EItemAnimator().isRunning()==true。我发现使用onMoveFinished更好,因为这考虑到了删除项目后的重新排列。这是否意味着在onRemoveFinished()完成后,会执行一系列移动?我假设(可能是错误的)删除包含整个操作…我测试了它,它实际上是这样的:在onRemoveFinished之后,有一大堆onMoveFinished调用。谢谢你的提示。
swipeableRecyclerView.setSwipingEnabled(false);
swipeableRecyclerView.setItemAnimator(new DefaultItemAnimator() {

    @Override
    public void onRemoveFinished(RecyclerView.ViewHolder item) {
        swipeableRecyclerView.setSwipingEnabled(true);
    }
});