1047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar/*
2ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * Copyright 2018 The Android Open Source Project
3047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar *
4047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar * Licensed under the Apache License, Version 2.0 (the "License");
5047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar * you may not use this file except in compliance with the License.
6047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar * You may obtain a copy of the License at
7047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar *
8047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar *      http://www.apache.org/licenses/LICENSE-2.0
9047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar *
10047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar * Unless required by applicable law or agreed to in writing, software
11047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar * distributed under the License is distributed on an "AS IS" BASIS,
12047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar * See the License for the specific language governing permissions and
14047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar * limitations under the License.
15047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar */
16047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar
17ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikaspackage androidx.recyclerview.widget;
18047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar
19754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikasimport static org.junit.Assert.assertEquals;
20754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikasimport static org.junit.Assert.assertFalse;
21754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikasimport static org.junit.Assert.assertNotNull;
22754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikasimport static org.junit.Assert.assertTrue;
230a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar
2435232c6eaeb9b99f390cb8ef0ac83bf45fa0b3faAurimas Liutikasimport android.support.test.filters.LargeTest;
250a017072206f93474ccd2706e7983c2ff778b904Yigit Boyarimport android.support.test.runner.AndroidJUnit4;
269457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyarimport android.util.Log;
27047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyarimport android.view.View;
28047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyarimport android.view.ViewGroup;
29047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyarimport android.widget.TextView;
30047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar
31c95a6f1f125ad3a7e1f9f79bccf4b2603bc40ebaAurimas Liutikasimport androidx.annotation.NonNull;
32c95a6f1f125ad3a7e1f9f79bccf4b2603bc40ebaAurimas Liutikas
33754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikasimport org.junit.Before;
34754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikasimport org.junit.Test;
35754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikasimport org.junit.runner.RunWith;
36754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikas
37047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyarimport java.util.ArrayList;
389457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyarimport java.util.Arrays;
39047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyarimport java.util.HashSet;
40047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyarimport java.util.List;
41047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyarimport java.util.Set;
429457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyarimport java.util.concurrent.Semaphore;
43047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyarimport java.util.concurrent.TimeUnit;
44047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar
4535232c6eaeb9b99f390cb8ef0ac83bf45fa0b3faAurimas Liutikas@LargeTest
460a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar@RunWith(AndroidJUnit4.class)
470a017072206f93474ccd2706e7983c2ff778b904Yigit Boyarpublic class DefaultItemAnimatorTest extends BaseRecyclerViewInstrumentationTest {
48047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar
499457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar    private static final String TAG = "DefaultItemAnimatorTest";
509457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar    Throwable mainThreadException;
519457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar
52047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar    DefaultItemAnimator mAnimator;
53047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar    Adapter mAdapter;
54047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar    ViewGroup mDummyParent;
559457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar    List<RecyclerView.ViewHolder> mExpectedItems = new ArrayList<RecyclerView.ViewHolder>();
56047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar
57047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar    Set<RecyclerView.ViewHolder> mRemoveFinished = new HashSet<RecyclerView.ViewHolder>();
58047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar    Set<RecyclerView.ViewHolder> mAddFinished = new HashSet<RecyclerView.ViewHolder>();
59047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar    Set<RecyclerView.ViewHolder> mMoveFinished = new HashSet<RecyclerView.ViewHolder>();
60047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar    Set<RecyclerView.ViewHolder> mChangeFinished = new HashSet<RecyclerView.ViewHolder>();
61047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar
629457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar    Semaphore mExpectedItemCount = new Semaphore(0);
639457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar
640a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    @Before
650a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    public void setUp() throws Exception {
66121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar        mAnimator = new DefaultItemAnimator() {
67047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar            @Override
68047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar            public void onRemoveFinished(RecyclerView.ViewHolder item) {
699457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                try {
709457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                    assertTrue(mRemoveFinished.add(item));
719457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                    onFinished(item);
729457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                } catch (Throwable t) {
739457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                    postExceptionToInstrumentation(t);
749457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                }
75047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar            }
76047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar
77047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar            @Override
78047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar            public void onAddFinished(RecyclerView.ViewHolder item) {
799457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                try {
809457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                    assertTrue(mAddFinished.add(item));
819457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                    onFinished(item);
829457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                } catch (Throwable t) {
839457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                    postExceptionToInstrumentation(t);
849457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                }
85047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar            }
86047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar
87047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar            @Override
88047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar            public void onMoveFinished(RecyclerView.ViewHolder item) {
899457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                try {
909457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                    assertTrue(mMoveFinished.add(item));
919457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                    onFinished(item);
929457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                } catch (Throwable t) {
939457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                    postExceptionToInstrumentation(t);
949457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                }
95047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar            }
96047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar
97047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar            @Override
98121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar            public void onChangeFinished(RecyclerView.ViewHolder item, boolean oldItem) {
999457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                try {
1009457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                    assertTrue(mChangeFinished.add(item));
1019457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                    onFinished(item);
1029457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                } catch (Throwable t) {
1039457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                    postExceptionToInstrumentation(t);
1049457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                }
105047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar            }
106047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar
1079457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar            private void onFinished(RecyclerView.ViewHolder item) {
1089457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                assertNotNull(mExpectedItems.remove(item));
1099457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                mExpectedItemCount.release(1);
110047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar            }
111121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar        };
112121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar        mAdapter = new Adapter(20);
113a90fb62f06861beb3af9f9b3356ef0bb0685547cYigit Boyar        mDummyParent = getActivity().getContainer();
114047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar    }
115047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar
116e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas    @Override
1179457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar    void checkForMainThreadException() throws Throwable {
1189457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        if (mainThreadException != null) {
1199457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar            throw mainThreadException;
1209457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        }
1219457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar    }
1229457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar
1230a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    @Test
1240a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    public void reUseWithPayload() {
125abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar        RecyclerView.ViewHolder vh = new ViewHolder(new TextView(getActivity()));
126abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar        assertFalse(mAnimator.canReuseUpdatedViewHolder(vh, new ArrayList<>()));
127abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar        assertTrue(mAnimator.canReuseUpdatedViewHolder(vh, Arrays.asList((Object) "a")));
128abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar    }
129abea494886a17e7a51080ab5e9c2ca041c533353Yigit Boyar
1309457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar    void expectItems(RecyclerView.ViewHolder... viewHolders) {
1319457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        mExpectedItems.addAll(Arrays.asList(viewHolders));
1329457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar    }
1339457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar
1349457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar    void runAndWait(int itemCount, int seconds) throws Throwable {
1359457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        runAndWait(itemCount, seconds, null);
136047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar    }
137047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar
1389457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar    void runAndWait(int itemCount, int seconds, final ThrowingRunnable postRun) throws Throwable {
13942e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityRule.runOnUiThread(new Runnable() {
140047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar            @Override
141047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar            public void run() {
142047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar                mAnimator.runPendingAnimations();
1439457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                if (postRun != null) {
1449457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                    try {
1459457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                        postRun.run();
1469457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                    } catch (Throwable e) {
1479457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                        throw new RuntimeException(e);
1489457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                    }
1499457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                }
150047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar            }
151047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar        });
1529457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        waitForItems(itemCount, seconds);
1539457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        checkForMainThreadException();
154047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar    }
155047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar
1569457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar    void waitForItems(int itemCount, int seconds) throws InterruptedException {
1579457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        assertTrue("all vh animations should end",
1589457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                mExpectedItemCount.tryAcquire(itemCount, seconds, TimeUnit.SECONDS));
1599457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        assertEquals("all expected finish events should happen", 0, mExpectedItems.size());
1609457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        // wait one more second for unwanted
1619457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        assertFalse("should not receive any more permits",
1629457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                mExpectedItemCount.tryAcquire(1, 2, TimeUnit.SECONDS));
163047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar    }
164047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar
1650a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    @Test
1660a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    public void animateAdd() throws Throwable {
167047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar        ViewHolder vh = createViewHolder(1);
1689457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        expectItems(vh);
169047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar        assertTrue(animateAdd(vh));
170047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar        assertTrue(mAnimator.isRunning());
1719457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        runAndWait(1, 1);
172047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar    }
173047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar
1740a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    @Test
1750a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    public void animateRemove() throws Throwable {
176047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar        ViewHolder vh = createViewHolder(1);
1779457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        expectItems(vh);
178047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar        assertTrue(animateRemove(vh));
179047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar        assertTrue(mAnimator.isRunning());
1809457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        runAndWait(1, 1);
181047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar    }
182047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar
1830a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    @Test
1840a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    public void animateMove() throws Throwable {
185047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar        ViewHolder vh = createViewHolder(1);
1869457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        expectItems(vh);
187047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar        assertTrue(animateMove(vh, 0, 0, 100, 100));
188047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar        assertTrue(mAnimator.isRunning());
1899457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        runAndWait(1, 1);
190047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar    }
191047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar
1920a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    @Test
1930a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    public void animateChange() throws Throwable {
194047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar        ViewHolder vh = createViewHolder(1);
195047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar        ViewHolder vh2 = createViewHolder(2);
1969457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        expectItems(vh, vh2);
197047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar        assertTrue(animateChange(vh, vh2, 0, 0, 100, 100));
198047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar        assertTrue(mAnimator.isRunning());
1999457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        runAndWait(2, 1);
2009457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar    }
2019457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar
2029457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar    public void cancelBefore(int count, final RecyclerView.ViewHolder... toCancel)
2039457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar            throws Throwable {
2049457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        cancelTest(true, count, toCancel);
2059457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar    }
2069457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar
2079457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar    public void cancelAfter(int count, final RecyclerView.ViewHolder... toCancel)
2089457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar            throws Throwable {
2099457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        cancelTest(false, count, toCancel);
2109457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar    }
2119457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar
2129457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar    public void cancelTest(boolean before, int count, final RecyclerView.ViewHolder... toCancel) throws Throwable {
2139457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        if (before) {
2149457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar            endAnimations(toCancel);
2159457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar            runAndWait(count, 1);
2169457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        } else {
2179457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar            runAndWait(count, 1, new ThrowingRunnable() {
2189457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                @Override
2199457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                public void run() throws Throwable {
2209457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                    endAnimations(toCancel);
2219457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                }
2229457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar            });
2239457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        }
2249457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar    }
2259457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar
2260a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    @Test
2270a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    public void cancelAddBefore() throws Throwable {
2289457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        final ViewHolder vh = createViewHolder(1);
2299457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        expectItems(vh);
2309457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        assertTrue(animateAdd(vh));
2319457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        cancelBefore(1, vh);
2329457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar    }
2339457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar
2340a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    @Test
2350a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    public void cancelAddAfter() throws Throwable {
2369457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        final ViewHolder vh = createViewHolder(1);
2379457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        expectItems(vh);
2389457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        assertTrue(animateAdd(vh));
2399457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        cancelAfter(1, vh);
2409457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar    }
2419457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar
2420a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    @Test
2430a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    public void cancelMoveBefore() throws Throwable {
2449457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        ViewHolder vh = createViewHolder(1);
2459457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        expectItems(vh);
2469457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        assertTrue(animateMove(vh, 10, 10, 100, 100));
2479457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        cancelBefore(1, vh);
2489457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar    }
2499457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar
2500a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    @Test
2510a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    public void cancelMoveAfter() throws Throwable {
2529457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        ViewHolder vh = createViewHolder(1);
2539457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        expectItems(vh);
2549457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        assertTrue(animateMove(vh, 10, 10, 100, 100));
2559457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        cancelAfter(1, vh);
2569457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar    }
2579457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar
2580a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    @Test
2590a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    public void cancelRemove() throws Throwable {
2609457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        ViewHolder vh = createViewHolder(1);
2619457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        expectItems(vh);
2629457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        assertTrue(animateRemove(vh));
2639457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        endAnimations(vh);
2649457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        runAndWait(1, 1);
2659457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar    }
2669457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar
2670a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    @Test
2680a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    public void cancelChangeOldBefore() throws Throwable {
2699457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        cancelChangeOldTest(true);
2709457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar    }
2710a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    @Test
2720a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    public void cancelChangeOldAfter() throws Throwable {
2739457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        cancelChangeOldTest(false);
2749457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar    }
2759457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar
2769457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar    public void cancelChangeOldTest(boolean before) throws Throwable {
2779457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        ViewHolder vh = createViewHolder(1);
2789457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        ViewHolder vh2 = createViewHolder(1);
2799457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        expectItems(vh, vh2);
2809457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        assertTrue(animateChange(vh, vh2, 20, 20, 100, 100));
2819457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        cancelTest(before, 2, vh);
2829457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar    }
2839457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar
2840a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    @Test
2850a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    public void cancelChangeNewBefore() throws Throwable {
2869457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        cancelChangeNewTest(true);
2879457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar    }
2889457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar
2890a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    @Test
2900a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    public void cancelChangeNewAfter() throws Throwable {
2919457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        cancelChangeNewTest(false);
2929457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar    }
2939457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar
2949457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar    public void cancelChangeNewTest(boolean before) throws Throwable {
2959457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        ViewHolder vh = createViewHolder(1);
2969457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        ViewHolder vh2 = createViewHolder(1);
2979457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        expectItems(vh, vh2);
2989457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        assertTrue(animateChange(vh, vh2, 20, 20, 100, 100));
2999457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        cancelTest(before, 2, vh2);
3009457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar    }
3019457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar
3020a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    @Test
3030a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    public void cancelChangeBothBefore() throws Throwable {
3049457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        cancelChangeBothTest(true);
3059457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar    }
3069457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar
3070a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    @Test
3080a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    public void cancelChangeBothAfter() throws Throwable {
3099457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        cancelChangeBothTest(false);
3109457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar    }
3119457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar
3129457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar    public void cancelChangeBothTest(boolean before) throws Throwable {
3139457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        ViewHolder vh = createViewHolder(1);
3149457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        ViewHolder vh2 = createViewHolder(1);
3159457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        expectItems(vh, vh2);
3169457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        assertTrue(animateChange(vh, vh2, 20, 20, 100, 100));
3179457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        cancelTest(before, 2, vh, vh2);
3189457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar    }
3199457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar
3209457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar    void endAnimations(final RecyclerView.ViewHolder... vhs) throws Throwable {
32142e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityRule.runOnUiThread(new Runnable() {
3229457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar            @Override
3239457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar            public void run() {
3249457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                for (RecyclerView.ViewHolder vh : vhs) {
3259457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                    mAnimator.endAnimation(vh);
3269457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar                }
3279457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar            }
3289457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        });
329047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar    }
330047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar
331047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar    boolean animateAdd(final RecyclerView.ViewHolder vh) throws Throwable {
332047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar        final boolean[] result = new boolean[1];
33342e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityRule.runOnUiThread(new Runnable() {
334047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar            @Override
335047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar            public void run() {
336047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar                result[0] = mAnimator.animateAdd(vh);
337047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar            }
338047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar        });
339047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar        return result[0];
340047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar    }
341047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar
342047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar    boolean animateRemove(final RecyclerView.ViewHolder vh) throws Throwable {
343047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar        final boolean[] result = new boolean[1];
34442e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityRule.runOnUiThread(new Runnable() {
345047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar            @Override
346047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar            public void run() {
347047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar                result[0] = mAnimator.animateRemove(vh);
348047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar            }
349047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar        });
350047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar        return result[0];
351047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar    }
352047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar
353047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar    boolean animateMove(final RecyclerView.ViewHolder vh, final int fromX, final int fromY,
354047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar            final int toX, final int toY) throws Throwable {
355047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar        final boolean[] result = new boolean[1];
35642e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityRule.runOnUiThread(new Runnable() {
357047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar            @Override
358047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar            public void run() {
359047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar                result[0] = mAnimator.animateMove(vh, fromX, fromY, toX, toY);
360047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar            }
361047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar        });
362047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar        return result[0];
363047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar    }
364047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar
365047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar    boolean animateChange(final RecyclerView.ViewHolder oldHolder,
366047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar            final RecyclerView.ViewHolder newHolder,
367047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar            final int fromX, final int fromY, final int toX, final int toY) throws Throwable {
368047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar        final boolean[] result = new boolean[1];
36942e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityRule.runOnUiThread(new Runnable() {
370047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar            @Override
371047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar            public void run() {
372047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar                result[0] = mAnimator.animateChange(oldHolder, newHolder, fromX, fromY, toX, toY);
373047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar            }
374047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar        });
375047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar        return result[0];
376047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar    }
377047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar
378047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar    private ViewHolder createViewHolder(final int pos) throws Throwable {
379047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar        final ViewHolder vh = mAdapter.createViewHolder(mDummyParent, 1);
38042e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityRule.runOnUiThread(new Runnable() {
381047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar            @Override
382047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar            public void run() {
383047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar                mAdapter.bindViewHolder(vh, pos);
384047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar                mDummyParent.addView(vh.itemView);
385047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar            }
386047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar        });
387047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar
388047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar        return vh;
389047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar    }
390047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar
391e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas    @Override
3929457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar    void postExceptionToInstrumentation(Throwable t) {
3939457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        if (mainThreadException == null) {
3949457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar            mainThreadException = t;
3959457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        } else {
3969457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar            Log.e(TAG, "skipping secondary main thread exception", t);
3979457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar        }
3989457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar    }
3999457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar
400047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar
401047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar    private class Adapter extends RecyclerView.Adapter<ViewHolder> {
402047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar
403047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar        List<String> mItems;
404047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar
405047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar        private Adapter(int count) {
4060a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar            mItems = new ArrayList<>();
407047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar            for (int i = 0; i < count; i++) {
408047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar                mItems.add("item-" + i);
409047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar            }
410047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar        }
411047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar
412047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar        @Override
4138a11e6829c522aa1efcc903afa4c01d337082eabChris Craik        public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
414047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar            return new ViewHolder(new TextView(parent.getContext()));
415047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar        }
416047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar
417047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar        @Override
4188a11e6829c522aa1efcc903afa4c01d337082eabChris Craik        public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
419047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar            holder.bind(mItems.get(position));
420047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar        }
421047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar
422047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar        @Override
423047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar        public int getItemCount() {
424047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar            return mItems.size();
425047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar        }
426047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar    }
427047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar
428047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar    private class ViewHolder extends RecyclerView.ViewHolder {
429047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar
430047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar        String mBindedText;
431047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar
432047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar        public ViewHolder(View itemView) {
433047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar            super(itemView);
434047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar        }
435047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar
436047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar        public void bind(String text) {
437047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar            mBindedText = text;
438047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar            ((TextView) itemView).setText(text);
439047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar        }
440047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar    }
4419457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar
4429457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar    private interface ThrowingRunnable {
4430a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar        void run() throws Throwable;
4449457c0c167cca5aafe971fb2eb75f4a43c07ec05Yigit Boyar    }
445047e1151b1ce6965f5578eac83ee1ac3cf524ba7Yigit Boyar}
446