From a5c564640896a9200b984bdf56e1989361a38657 Mon Sep 17 00:00:00 2001 From: Nicholas Corder Date: Fri, 29 Sep 2017 17:50:41 -0700 Subject: [PATCH] Block item click callback during item layout. Adding a RecyclerView.NO_POSITION != viewHolder.getAdapterPosition() check inside of the click listener wrapper ensures we do not call the click listener when the item is going through a layout. There was a need to make a change to the ControllerLifecycleHelper to ensure that click still passed as the adapter was always supplying `NO_POSITION` for unit tests. The simplest way to get the basic functionality was to spy the viewHolder, and stub this method. ISSUE #293 --- .../epoxy/WrappedEpoxyModelClickListener.java | 7 ++++++- .../airbnb/epoxy/ControllerLifecycleHelper.java | 16 ++++++++++++---- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/epoxy-adapter/src/main/java/com/airbnb/epoxy/WrappedEpoxyModelClickListener.java b/epoxy-adapter/src/main/java/com/airbnb/epoxy/WrappedEpoxyModelClickListener.java index 8a9059c4ac..893b81c130 100644 --- a/epoxy-adapter/src/main/java/com/airbnb/epoxy/WrappedEpoxyModelClickListener.java +++ b/epoxy-adapter/src/main/java/com/airbnb/epoxy/WrappedEpoxyModelClickListener.java @@ -1,5 +1,6 @@ package com.airbnb.epoxy; +import android.support.v7.widget.RecyclerView; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnLongClickListener; @@ -54,7 +55,11 @@ public void onClick(View v) { if (originalClickListener == null) { throw new IllegalStateException("Long click listener was set."); } - originalClickListener.onClick(model, object, v, holder.getAdapterPosition()); + + final int adapterPosition = holder.getAdapterPosition(); + if (adapterPosition != RecyclerView.NO_POSITION) { + originalClickListener.onClick(model, object, v, adapterPosition); + } } @Override diff --git a/epoxy-integrationtest/src/test/java/com/airbnb/epoxy/ControllerLifecycleHelper.java b/epoxy-integrationtest/src/test/java/com/airbnb/epoxy/ControllerLifecycleHelper.java index a787d3fafd..bf13333d9a 100644 --- a/epoxy-integrationtest/src/test/java/com/airbnb/epoxy/ControllerLifecycleHelper.java +++ b/epoxy-integrationtest/src/test/java/com/airbnb/epoxy/ControllerLifecycleHelper.java @@ -8,6 +8,9 @@ import java.util.Collections; import java.util.List; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + class ControllerLifecycleHelper { private EpoxyViewHolder viewHolder; @@ -36,11 +39,16 @@ public View bindModel(EpoxyModel model) { } static EpoxyViewHolder createViewHolder(BaseEpoxyAdapter adapter, int position) { - int itemViewType = adapter.getItemViewType(position); - return adapter.onCreateViewHolder( - new FrameLayout(RuntimeEnvironment.application), - itemViewType + final EpoxyViewHolder viewHolder = spy( + adapter.onCreateViewHolder( + new FrameLayout(RuntimeEnvironment.application), + adapter.getItemViewType(position) + ) ); + + // The simplest way to inject the position for testing. + when(viewHolder.getAdapterPosition()).thenReturn(position); + return viewHolder; } void recycleLastBoundModel(EpoxyController controller) {