ItemAnimatorV2ApiTest.java revision f1b288ec2104488f4a92e911b0ab80c8f0f3e9d1
1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package android.support.v7.widget;
17
18import android.support.annotation.NonNull;
19import android.support.annotation.Nullable;
20import android.test.suitebuilder.annotation.MediumTest;
21
22import java.util.ArrayList;
23import java.util.HashMap;
24import java.util.List;
25import java.util.Map;
26import java.util.concurrent.atomic.AtomicInteger;
27
28import static android.support.v7.widget.RecyclerView.ItemAnimator.FLAG_CHANGED;
29import static android.support.v7.widget.RecyclerView.ItemAnimator.FLAG_MOVED;
30import static android.support.v7.widget.RecyclerView.ItemAnimator.FLAG_REMOVED;
31
32/**
33 * Includes tests for the new RecyclerView animations API (v2).
34 */
35@MediumTest
36public class ItemAnimatorV2ApiTest extends BaseRecyclerViewAnimationsTest {
37    @Override
38    protected RecyclerView.ItemAnimator createItemAnimator() {
39        return mAnimator;
40    }
41
42    public void testChangeMovedOutside() throws Throwable {
43        setupBasic(10);
44        final RecyclerView.ViewHolder target = mRecyclerView.findViewHolderForAdapterPosition(9);
45        mLayoutManager.expectLayouts(2);
46        mLayoutManager.mOnLayoutCallbacks.mLayoutItemCount = 9;
47        mTestAdapter.changeAndNotify(9, 1);
48        mLayoutManager.waitForLayout(2);
49        // changed item shold not be laid out and should just receive disappear
50        LoggingInfo pre = mAnimator.preLayoutInfoMap.get(target);
51        assertNotNull("test sanity", pre);
52        assertNull("test sanity", mAnimator.postLayoutInfoMap.get(target));
53        assertTrue(mAnimator.animateChangeList.isEmpty());
54        assertEquals(1, mAnimator.animateDisappearanceList.size());
55        assertEquals(new AnimateDisappearance(target, pre, null),
56                mAnimator.animateDisappearanceList.get(0));
57        // This is kind of problematic because layout manager will never layout the updated
58        // version of this view since it went out of bounds and it won't show up in scrap.
59        // I don't think we can do much better since other option is to bind a fresh view
60    }
61
62    public void testSimpleAdd() throws Throwable {
63        setupBasic(10);
64        mLayoutManager.expectLayouts(2);
65        mTestAdapter.addAndNotify(2, 1);
66        mLayoutManager.waitForLayout(2);
67        RecyclerView.ViewHolder vh = mRecyclerView.findViewHolderForAdapterPosition(2);
68        assertEquals(1, mAnimator.animateAppearanceList.size());
69        AnimateAppearance log = mAnimator.animateAppearanceList.get(0);
70        assertSame(vh, log.viewHolder);
71        assertNull(log.preInfo);
72        assertEquals(0, log.postInfo.changeFlags);
73        // the first two should not receive anything
74        for (int i = 0; i < 2; i++) {
75            RecyclerView.ViewHolder other = mRecyclerView.findViewHolderForAdapterPosition(i);
76            assertEquals(0, mAnimator.preLayoutInfoMap.get(other).changeFlags);
77        }
78        for (int i = 3; i < mTestAdapter.getItemCount(); i++) {
79            RecyclerView.ViewHolder other = mRecyclerView.findViewHolderForAdapterPosition(i);
80            assertEquals(FLAG_MOVED, mAnimator.preLayoutInfoMap.get(other).changeFlags);
81        }
82        checkForMainThreadException();
83    }
84
85    public void testSimpleRemove() throws Throwable {
86        setupBasic(10);
87        RecyclerView.ViewHolder vh = mRecyclerView.findViewHolderForAdapterPosition(2);
88        mLayoutManager.expectLayouts(2);
89        mTestAdapter.deleteAndNotify(2, 1);
90        mLayoutManager.waitForLayout(2);
91        checkForMainThreadException();
92        assertEquals(1, mAnimator.animateDisappearanceList.size());
93        AnimateDisappearance log = mAnimator.animateDisappearanceList.get(0);
94        assertSame(vh, log.viewHolder);
95        assertFalse(mAnimator.postLayoutInfoMap.containsKey(vh));
96        assertEquals(FLAG_REMOVED, log.preInfo.changeFlags);
97        // the first two should not receive anything
98        for (int i = 0; i < 2; i++) {
99            RecyclerView.ViewHolder other = mRecyclerView.findViewHolderForAdapterPosition(i);
100            assertEquals(0, mAnimator.preLayoutInfoMap.get(other).changeFlags);
101        }
102        for (int i = 3; i < mTestAdapter.getItemCount(); i++) {
103            RecyclerView.ViewHolder other = mRecyclerView.findViewHolderForAdapterPosition(i);
104            assertEquals(FLAG_MOVED, mAnimator.preLayoutInfoMap.get(other).changeFlags);
105        }
106        checkForMainThreadException();
107    }
108
109    public void testSimpleUpdate() throws Throwable {
110        setupBasic(10);
111        RecyclerView.ViewHolder vh = mRecyclerView.findViewHolderForAdapterPosition(2);
112        mLayoutManager.expectLayouts(2);
113        mTestAdapter.changeAndNotify(2, 1);
114        mLayoutManager.waitForLayout(2);
115        assertEquals(1, mAnimator.animateChangeList.size());
116        AnimateChange log = mAnimator.animateChangeList.get(0);
117        assertSame(vh, log.viewHolder);
118        assertSame(vh, log.newHolder);
119        assertTrue(mAnimator.preLayoutInfoMap.containsKey(vh));
120        assertTrue(mAnimator.postLayoutInfoMap.containsKey(vh));
121        assertEquals(FLAG_CHANGED, log.preInfo.changeFlags);
122        assertEquals(0, log.postInfo.changeFlags);
123        //others should not receive anything
124        for (int i = 0; i < mTestAdapter.getItemCount(); i++) {
125            if (i == 2) {
126                continue;
127            }
128            RecyclerView.ViewHolder other = mRecyclerView.findViewHolderForAdapterPosition(i);
129            assertEquals(0, mAnimator.preLayoutInfoMap.get(other).changeFlags);
130        }
131        checkForMainThreadException();
132    }
133
134    public void testUpdateWithDuplicateViewHolder() throws Throwable {
135        setupBasic(10);
136        final RecyclerView.ViewHolder vh = mRecyclerView.findViewHolderForAdapterPosition(2);
137        mAnimator.canReUseCallback = new CanReUseCallback() {
138            @Override
139            public boolean canReUse(RecyclerView.ViewHolder viewHolder, List<Object> payloads) {
140                assertSame(viewHolder, vh);
141                return false;
142            }
143        };
144        mLayoutManager.expectLayouts(2);
145        mTestAdapter.changeAndNotify(2, 1);
146        mLayoutManager.waitForLayout(2);
147        final RecyclerView.ViewHolder newVh = mRecyclerView.findViewHolderForAdapterPosition(2);
148        assertNotSame(vh, newVh);
149        assertEquals(1, mAnimator.animateChangeList.size());
150        AnimateChange log = mAnimator.animateChangeList.get(0);
151        assertSame(vh, log.viewHolder);
152        assertSame(newVh, log.newHolder);
153        assertNull(vh.itemView.getParent());
154        assertTrue(mAnimator.preLayoutInfoMap.containsKey(vh));
155        assertFalse(mAnimator.postLayoutInfoMap.containsKey(vh));
156        assertTrue(mAnimator.postLayoutInfoMap.containsKey(newVh));
157        assertEquals(FLAG_CHANGED, log.preInfo.changeFlags);
158        assertEquals(0, log.postInfo.changeFlags);
159        //others should not receive anything
160        for (int i = 0; i < mTestAdapter.getItemCount(); i++) {
161            if (i == 2) {
162                continue;
163            }
164            RecyclerView.ViewHolder other = mRecyclerView.findViewHolderForAdapterPosition(i);
165            assertEquals(0, mAnimator.preLayoutInfoMap.get(other).changeFlags);
166        }
167        checkForMainThreadException();
168    }
169
170    public void testUpdateWithOneDuplicateAndOneInPlace() throws Throwable {
171        setupBasic(10);
172        final RecyclerView.ViewHolder replaced = mRecyclerView.findViewHolderForAdapterPosition(2);
173        final RecyclerView.ViewHolder reused = mRecyclerView.findViewHolderForAdapterPosition(3);
174        mAnimator.canReUseCallback = new CanReUseCallback() {
175            @Override
176            public boolean canReUse(RecyclerView.ViewHolder viewHolder, List<Object> payloads) {
177                if (viewHolder == replaced) {
178                    return false;
179                } else if (viewHolder == reused) {
180                    return true;
181                }
182                fail("unpexpected view");
183                return false;
184            }
185        };
186        mLayoutManager.expectLayouts(2);
187        mTestAdapter.changeAndNotify(2, 2);
188        mLayoutManager.waitForLayout(2);
189        final RecyclerView.ViewHolder newVh = mRecyclerView.findViewHolderForAdapterPosition(2);
190
191        assertNotSame(replaced, newVh);
192        assertSame(reused, mRecyclerView.findViewHolderForAdapterPosition(3));
193
194        assertEquals(2, mAnimator.animateChangeList.size());
195        AnimateChange logReplaced = null, logReused = null;
196        for (AnimateChange change : mAnimator.animateChangeList) {
197            if (change.newHolder == change.viewHolder) {
198                logReused = change;
199            } else {
200                logReplaced = change;
201            }
202        }
203        assertNotNull(logReplaced);
204        assertNotNull(logReused);
205        assertSame(replaced, logReplaced.viewHolder);
206        assertSame(newVh, logReplaced.newHolder);
207        assertSame(reused, logReused.viewHolder);
208        assertSame(reused, logReused.newHolder);
209
210        assertTrue(mAnimator.preLayoutInfoMap.containsKey(replaced));
211        assertTrue(mAnimator.preLayoutInfoMap.containsKey(reused));
212
213        assertTrue(mAnimator.postLayoutInfoMap.containsKey(newVh));
214        assertTrue(mAnimator.postLayoutInfoMap.containsKey(reused));
215        assertFalse(mAnimator.postLayoutInfoMap.containsKey(replaced));
216
217        assertEquals(FLAG_CHANGED, logReplaced.preInfo.changeFlags);
218        assertEquals(FLAG_CHANGED, logReused.preInfo.changeFlags);
219
220        assertEquals(0, logReplaced.postInfo.changeFlags);
221        assertEquals(0, logReused.postInfo.changeFlags);
222        //others should not receive anything
223        for (int i = 0; i < mTestAdapter.getItemCount(); i++) {
224            if (i == 2 || i == 3) {
225                continue;
226            }
227            RecyclerView.ViewHolder other = mRecyclerView.findViewHolderForAdapterPosition(i);
228            assertEquals(0, mAnimator.preLayoutInfoMap.get(other).changeFlags);
229        }
230        checkForMainThreadException();
231    }
232
233    public void testChangeToDisappear() throws Throwable {
234        setupBasic(10);
235        RecyclerView.ViewHolder vh = mRecyclerView.findViewHolderForAdapterPosition(9);
236        mLayoutManager.mOnLayoutCallbacks.mLayoutItemCount = 9;
237        mLayoutManager.expectLayouts(2);
238        mTestAdapter.changeAndNotify(9, 1);
239        mLayoutManager.waitForLayout(2);
240        assertEquals(1, mAnimator.animateDisappearanceList.size());
241        AnimateDisappearance log = mAnimator.animateDisappearanceList.get(0);
242        assertSame(vh, log.viewHolder);
243        assertFalse(mAnimator.postLayoutInfoMap.containsKey(vh));
244        assertEquals(FLAG_CHANGED, log.preInfo.changeFlags);
245        assertEquals(0, mAnimator.animateChangeList.size());
246        assertEquals(0, mAnimator.animateAppearanceList.size());
247        assertEquals(9, mAnimator.animatePersistenceList.size());
248        checkForMainThreadException();
249    }
250
251    public void testUpdatePayload() throws Throwable {
252        setupBasic(10);
253        final RecyclerView.ViewHolder vh = mRecyclerView.findViewHolderForAdapterPosition(2);
254        final Object payload = new Object();
255        mAnimator.canReUseCallback = new CanReUseCallback() {
256            @Override
257            public boolean canReUse(RecyclerView.ViewHolder viewHolder, List<Object> payloads) {
258                assertSame(vh, viewHolder);
259                assertEquals(1, payloads.size());
260                assertSame(payload, payloads.get(0));
261                return true;
262            }
263        };
264        mLayoutManager.expectLayouts(2);
265        mTestAdapter.changeAndNotifyWithPayload(2, 1, payload);
266        mLayoutManager.waitForLayout(2);
267        assertEquals(1, mAnimator.animateChangeList.size());
268        AnimateChange log = mAnimator.animateChangeList.get(0);
269        assertSame(vh, log.viewHolder);
270        assertSame(vh, log.newHolder);
271        assertTrue(mAnimator.preLayoutInfoMap.containsKey(vh));
272        assertTrue(mAnimator.postLayoutInfoMap.containsKey(vh));
273        assertEquals(FLAG_CHANGED, log.preInfo.changeFlags);
274        assertEquals(0, log.postInfo.changeFlags);
275        assertNotNull(log.preInfo.payloads);
276        assertTrue(log.preInfo.payloads.contains(payload));
277        //others should not receive anything
278        for (int i = 0; i < mTestAdapter.getItemCount(); i++) {
279            if (i == 2) {
280                continue;
281            }
282            RecyclerView.ViewHolder other = mRecyclerView.findViewHolderForAdapterPosition(i);
283            assertEquals(0, mAnimator.preLayoutInfoMap.get(other).changeFlags);
284        }
285        checkForMainThreadException();
286    }
287
288    public void testNotifyDataSetChanged() throws Throwable {
289        TestAdapter adapter = new TestAdapter(10);
290        adapter.setHasStableIds(true);
291        setupBasic(10, 0, 10, adapter);
292        mLayoutManager.expectLayouts(1);
293        mTestAdapter.dispatchDataSetChanged();
294        mLayoutManager.waitForLayout(2);
295        assertEquals(10, mAnimator.animateChangeList.size());
296        for (AnimateChange change : mAnimator.animateChangeList) {
297            assertNotNull(change.preInfo);
298            assertNotNull(change.postInfo);
299            assertSame(change.preInfo.viewHolder, change.postInfo.viewHolder);
300        }
301        assertEquals(0, mAnimator.animatePersistenceList.size());
302        assertEquals(0, mAnimator.animateAppearanceList.size());
303        assertEquals(0, mAnimator.animateDisappearanceList.size());
304    }
305
306    public void testNotifyDataSetChangedWithoutStableIds() throws Throwable {
307        TestAdapter adapter = new TestAdapter(10);
308        adapter.setHasStableIds(false);
309        setupBasic(10, 0, 10, adapter);
310        mLayoutManager.expectLayouts(1);
311        mTestAdapter.dispatchDataSetChanged();
312        mLayoutManager.waitForLayout(2);
313        assertEquals(0, mAnimator.animateChangeList.size());
314        assertEquals(0, mAnimator.animatePersistenceList.size());
315        assertEquals(0, mAnimator.animateAppearanceList.size());
316        assertEquals(0, mAnimator.animateDisappearanceList.size());
317    }
318
319    public void testNotifyDataSetChangedWithAppearing() throws Throwable {
320        notifyDataSetChangedWithAppearing(false);
321    }
322
323    public void testNotifyDataSetChangedWithAppearingNotifyBoth() throws Throwable {
324        notifyDataSetChangedWithAppearing(true);
325    }
326
327    public void notifyDataSetChangedWithAppearing(final boolean notifyBoth) throws Throwable {
328        final TestAdapter adapter = new TestAdapter(10);
329        adapter.setHasStableIds(true);
330        setupBasic(10, 0, 10, adapter);
331        mLayoutManager.expectLayouts(1);
332        runTestOnUiThread(new Runnable() {
333            @Override
334            public void run() {
335                try {
336                    if (notifyBoth) {
337                        adapter.addAndNotify(2, 2);
338                    } else {
339                        adapter.mItems.add(2, new Item(2, "custom 1"));
340                        adapter.mItems.add(3, new Item(3, "custom 2"));
341                    }
342
343                    adapter.notifyDataSetChanged();
344                } catch (Throwable throwable) {
345                    throwable.printStackTrace();
346                }
347            }
348        });
349        mLayoutManager.waitForLayout(2);
350        assertEquals(10, mAnimator.animateChangeList.size());
351        assertEquals(0, mAnimator.animatePersistenceList.size());
352        assertEquals(2, mAnimator.animateAppearanceList.size());
353        assertEquals(0, mAnimator.animateDisappearanceList.size());
354    }
355
356    public void testNotifyDataSetChangedWithDispappearing() throws Throwable {
357        notifyDataSetChangedWithDispappearing(false);
358    }
359
360    public void testNotifyDataSetChangedWithDispappearingNotifyBoth() throws Throwable {
361        notifyDataSetChangedWithDispappearing(true);
362    }
363
364    public void notifyDataSetChangedWithDispappearing(final boolean notifyBoth) throws Throwable {
365        final TestAdapter adapter = new TestAdapter(10);
366        adapter.setHasStableIds(true);
367        setupBasic(10, 0, 10, adapter);
368        mLayoutManager.expectLayouts(1);
369        runTestOnUiThread(new Runnable() {
370            @Override
371            public void run() {
372                try {
373                    if (notifyBoth) {
374                        adapter.deleteAndNotify(2, 2);
375                    } else {
376                        adapter.mItems.remove(2);
377                        adapter.mItems.remove(2);
378                    }
379                    adapter.notifyDataSetChanged();
380                } catch (Throwable throwable) {
381                    throwable.printStackTrace();
382                }
383            }
384        });
385        mLayoutManager.waitForLayout(2);
386        assertEquals(8, mAnimator.animateChangeList.size());
387        assertEquals(0, mAnimator.animatePersistenceList.size());
388        assertEquals(0, mAnimator.animateAppearanceList.size());
389        assertEquals(2, mAnimator.animateDisappearanceList.size());
390    }
391
392    public void testNotifyUpdateWithChangedAdapterType() throws Throwable {
393        final AtomicInteger itemType = new AtomicInteger(1);
394        final TestAdapter adapter = new TestAdapter(10) {
395            @Override
396            public int getItemViewType(int position) {
397                return position == 2 ? itemType.get() : 20;
398            }
399        };
400        adapter.setHasStableIds(true);
401        setupBasic(10, 0, 10, adapter);
402        final RecyclerView.ViewHolder vh = mRecyclerView.findViewHolderForAdapterPosition(2);
403
404        mAnimator.canReUseCallback = new CanReUseCallback() {
405            @Override
406            public boolean canReUse(RecyclerView.ViewHolder viewHolder, List<Object> payloads) {
407                return viewHolder != vh;
408            }
409        };
410
411        mLayoutManager.expectLayouts(1);
412        itemType.set(3);
413        adapter.dispatchDataSetChanged();
414        mLayoutManager.waitForLayout(2);
415        final RecyclerView.ViewHolder newVh = mRecyclerView.findViewHolderForAdapterPosition(2);
416        // TODO we should be able to map old type to the new one but doing that change has some
417        // recycling side effects.
418        assertEquals(9, mAnimator.animateChangeList.size());
419        assertEquals(0, mAnimator.animatePersistenceList.size());
420        assertEquals(1, mAnimator.animateAppearanceList.size());
421        assertEquals(0, mAnimator.animateDisappearanceList.size());
422        assertNotSame(vh, newVh);
423        for (AnimateChange change : mAnimator.animateChangeList) {
424            if (change.viewHolder == vh) {
425                assertSame(change.newHolder, newVh);
426                assertSame(change.viewHolder, vh);
427            } else {
428                assertSame(change.newHolder, change.viewHolder);
429            }
430        }
431    }
432
433    LoggingV2Animator mAnimator = new LoggingV2Animator();
434
435    class LoggingV2Animator extends RecyclerView.ItemAnimator {
436
437        CanReUseCallback canReUseCallback = new CanReUseCallback() {
438            @Override
439            public boolean canReUse(RecyclerView.ViewHolder viewHolder, List<Object> payloads) {
440                return true;
441            }
442        };
443        Map<RecyclerView.ViewHolder, LoggingInfo> preLayoutInfoMap = new HashMap<>();
444        Map<RecyclerView.ViewHolder, LoggingInfo> postLayoutInfoMap = new HashMap<>();
445
446        List<AnimateAppearance> animateAppearanceList = new ArrayList<>();
447        List<AnimateDisappearance> animateDisappearanceList = new ArrayList<>();
448        List<AnimatePersistence> animatePersistenceList = new ArrayList<>();
449        List<AnimateChange> animateChangeList = new ArrayList<>();
450
451        @Override
452        public boolean canReuseUpdatedViewHolder(RecyclerView.ViewHolder viewHolder,
453                List<Object> payloads) {
454            return canReUseCallback.canReUse(viewHolder, payloads);
455        }
456
457        @NonNull
458        @Override
459        public ItemHolderInfo recordPreLayoutInformation(@NonNull RecyclerView.State state,
460                @NonNull RecyclerView.ViewHolder viewHolder,
461                @AdapterChanges int changeFlags, @NonNull List<Object> payloads) {
462            LoggingInfo loggingInfo = new LoggingInfo(viewHolder, changeFlags, payloads);
463            preLayoutInfoMap.put(viewHolder, loggingInfo);
464            return loggingInfo;
465        }
466
467        @NonNull
468        @Override
469        public ItemHolderInfo recordPostLayoutInformation(@NonNull RecyclerView.State state,
470                @NonNull RecyclerView.ViewHolder viewHolder) {
471            LoggingInfo loggingInfo = new LoggingInfo(viewHolder, 0, null);
472            postLayoutInfoMap.put(viewHolder, loggingInfo);
473            return loggingInfo;
474        }
475
476        @Override
477        public boolean animateDisappearance(@NonNull RecyclerView.ViewHolder viewHolder,
478                @NonNull ItemHolderInfo preLayoutInfo,
479                @Nullable ItemHolderInfo postLayoutInfo) {
480            animateDisappearanceList.add(new AnimateDisappearance(viewHolder,
481                    (LoggingInfo) preLayoutInfo, (LoggingInfo) postLayoutInfo));
482            assertSame(preLayoutInfoMap.get(viewHolder), preLayoutInfo);
483            assertSame(postLayoutInfoMap.get(viewHolder), postLayoutInfo);
484            dispatchAnimationFinished(viewHolder);
485
486            return false;
487        }
488
489        @Override
490        public boolean animateAppearance(@NonNull RecyclerView.ViewHolder viewHolder,
491                ItemHolderInfo preInfo, @NonNull ItemHolderInfo postInfo) {
492            animateAppearanceList.add(
493                    new AnimateAppearance(viewHolder, (LoggingInfo) preInfo, (LoggingInfo) postInfo));
494            assertSame(preLayoutInfoMap.get(viewHolder), preInfo);
495            assertSame(postLayoutInfoMap.get(viewHolder), postInfo);
496            dispatchAnimationFinished(viewHolder);
497            return false;
498        }
499
500        @Override
501        public boolean animatePersistence(@NonNull RecyclerView.ViewHolder viewHolder,
502                @NonNull ItemHolderInfo preInfo, @NonNull ItemHolderInfo postInfo) {
503            animatePersistenceList.add(new AnimatePersistence(viewHolder, (LoggingInfo) preInfo,
504                    (LoggingInfo) postInfo));
505            dispatchAnimationFinished(viewHolder);
506            assertSame(preLayoutInfoMap.get(viewHolder), preInfo);
507            assertSame(postLayoutInfoMap.get(viewHolder), postInfo);
508            return false;
509        }
510
511        @Override
512        public boolean animateChange(@NonNull RecyclerView.ViewHolder oldHolder,
513                @NonNull RecyclerView.ViewHolder newHolder, @NonNull ItemHolderInfo preInfo,
514                @NonNull ItemHolderInfo postInfo) {
515            animateChangeList.add(new AnimateChange(oldHolder, newHolder, (LoggingInfo) preInfo,
516                    (LoggingInfo) postInfo));
517            if (oldHolder != null) {
518                dispatchAnimationFinished(oldHolder);
519                assertSame(preLayoutInfoMap.get(oldHolder), preInfo);
520            }
521            if (newHolder != null && oldHolder != newHolder) {
522                dispatchAnimationFinished(newHolder);
523                assertSame(postLayoutInfoMap.get(newHolder), postInfo);
524            }
525
526            return false;
527        }
528
529        @Override
530        public void runPendingAnimations() {
531
532        }
533
534        @Override
535        public void endAnimation(RecyclerView.ViewHolder item) {
536        }
537
538        @Override
539        public void endAnimations() {
540
541        }
542
543        @Override
544        public boolean isRunning() {
545            return false;
546        }
547    }
548
549    interface CanReUseCallback {
550
551        boolean canReUse(RecyclerView.ViewHolder viewHolder, List<Object> payloads);
552    }
553}
554