Last active
June 14, 2018 19:54
-
-
Save aballano/92257b6348312b541aa4f6b205eb14e4 to your computer and use it in GitHub Desktop.
Create an observable of long click events on RecyclerView items (refer to RxBinding tests for the whole picture).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.support.v7.widget.RecyclerView; | |
import android.view.View; | |
import rx.Observable; | |
import rx.Subscriber; | |
import rx.android.MainThreadSubscription; | |
import static rx.android.MainThreadSubscription.verifyMainThread; | |
final class RecyclerViewItemLongClickOnSubscribe implements Observable.OnSubscribe<Integer> { | |
final RecyclerView recyclerView; | |
public RecyclerViewItemLongClickOnSubscribe(RecyclerView recyclerView) { | |
this.recyclerView = recyclerView; | |
} | |
@Override public void call(final Subscriber<? super Integer> subscriber) { | |
verifyMainThread(); | |
final View.OnLongClickListener onLongClickListener = new View.OnLongClickListener() { | |
@Override public boolean onLongClick(View view) { | |
if (!subscriber.isUnsubscribed()) { | |
RecyclerView.ViewHolder holder = recyclerView.getChildViewHolder(view); | |
subscriber.onNext(holder.getAdapterPosition()); | |
return true; | |
} | |
return false; | |
} | |
}; | |
final RecyclerView.OnChildAttachStateChangeListener onAttachListener = new RecyclerView.OnChildAttachStateChangeListener() { | |
@Override public void onChildViewAttachedToWindow(View view) { | |
view.setOnLongClickListener(onLongClickListener); | |
} | |
@Override public void onChildViewDetachedFromWindow(View view) { | |
view.setOnLongClickListener(null); | |
} | |
}; | |
subscriber.add(new MainThreadSubscription() { | |
@Override protected void onUnsubscribe() { | |
recyclerView.removeOnChildAttachStateChangeListener(onAttachListener); | |
} | |
}); | |
recyclerView.addOnChildAttachStateChangeListener(onAttachListener); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@RunWith(AndroidJUnit4.class) | |
public final class RxRecyclerViewTest { | |
@Rule public final ActivityTestRule<RxRecyclerViewTestActivity> activityRule = | |
new ActivityTestRule<>(RxRecyclerViewTestActivity.class); | |
private final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); | |
RecyclerView view; | |
private ViewInteraction interaction; | |
private ViewDirtyIdlingResource viewDirtyIdler; | |
private View child; | |
@Before public void setUp() { | |
RxRecyclerViewTestActivity activity = activityRule.getActivity(); | |
view = activity.recyclerView; | |
child = new View(activityRule.getActivity()); | |
interaction = Espresso.onView(ViewMatchers.withId(android.R.id.primary)); | |
viewDirtyIdler = new ViewDirtyIdlingResource(activity); | |
Espresso.registerIdlingResources(viewDirtyIdler); | |
} | |
@After public void tearDown() { | |
Espresso.unregisterIdlingResources(viewDirtyIdler); | |
} | |
@Test public void itemsClicked() { | |
RecordingObserver<Integer> o = new RecordingObserver<>(); | |
Subscription subscription = RxRecyclerView.itemClick(view) | |
.subscribeOn(AndroidSchedulers.mainThread()) | |
.subscribe(o); | |
o.assertNoMoreEvents(); | |
final Adapter adapter = new Adapter(); | |
instrumentation.runOnMainSync(new Runnable() { | |
@Override public void run() { | |
view.setAdapter(adapter); | |
} | |
}); | |
for (int i = 0, childCount = view.getChildCount(); i < childCount; i++) { | |
final View childAt = view.getChildAt(i); | |
instrumentation.runOnMainSync(new Runnable() { | |
@Override public void run() { | |
childAt.performClick(); | |
} | |
}); | |
assertThat(o.takeNext()).isEqualTo(i); | |
} | |
subscription.unsubscribe(); | |
instrumentation.runOnMainSync(new Runnable() { | |
@Override public void run() { | |
view.getChildAt(0).performClick(); | |
} | |
}); | |
o.assertNoMoreEvents(); | |
} | |
@Test public void itemsLongClicked() { | |
RecordingObserver<Integer> o = new RecordingObserver<>(); | |
Subscription subscription = RxRecyclerView.itemLongClick(view) | |
.subscribeOn(AndroidSchedulers.mainThread()) | |
.subscribe(o); | |
o.assertNoMoreEvents(); | |
final Adapter adapter = new Adapter(); | |
instrumentation.runOnMainSync(new Runnable() { | |
@Override public void run() { | |
view.setAdapter(adapter); | |
} | |
}); | |
for (int i = 0, childCount = view.getChildCount(); i < childCount; i++) { | |
final View childAt = view.getChildAt(i); | |
instrumentation.runOnMainSync(new Runnable() { | |
@Override public void run() { | |
childAt.performLongClick(); | |
} | |
}); | |
assertThat(o.takeNext()).isEqualTo(i); | |
} | |
subscription.unsubscribe(); | |
instrumentation.runOnMainSync(new Runnable() { | |
@Override public void run() { | |
view.getChildAt(0).performLongClick(); | |
} | |
}); | |
o.assertNoMoreEvents(); | |
} | |
private static class Adapter extends RecyclerView.Adapter<ViewHolder> { | |
public Adapter() { | |
setHasStableIds(true); | |
} | |
@Override public ViewHolder onCreateViewHolder(ViewGroup parent, int position) { | |
TextView v = (TextView) LayoutInflater.from(parent.getContext()).inflate(android.R.layout.simple_list_item_1, parent, false); | |
return new ViewHolder(v); | |
} | |
@Override public void onBindViewHolder(ViewHolder holder, int position) { | |
holder.textView.setText(String.valueOf(position)); | |
} | |
@Override public int getItemCount() { | |
return 100; | |
} | |
@Override public long getItemId(int position) { | |
return position; | |
} | |
} | |
private static class ViewHolder extends RecyclerView.ViewHolder { | |
TextView textView; | |
public ViewHolder(TextView itemView) { | |
super(itemView); | |
this.textView = itemView; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment