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