1121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar/* 2ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * Copyright 2018 The Android Open Source Project 3121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar * 4121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar * Licensed under the Apache License, Version 2.0 (the "License"); 5121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar * you may not use this file except in compliance with the License. 6121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar * You may obtain a copy of the License at 7121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar * 8121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar * http://www.apache.org/licenses/LICENSE-2.0 9121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar * 10121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar * Unless required by applicable law or agreed to in writing, software 11121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar * distributed under the License is distributed on an "AS IS" BASIS, 12121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar * See the License for the specific language governing permissions and 14121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar * limitations under the License. 15121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar */ 16ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikaspackage androidx.recyclerview.widget; 17121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 18121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 1942e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikasimport static org.junit.Assert.assertEquals; 2042e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikasimport static org.junit.Assert.assertNotNull; 2142e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikasimport static org.junit.Assert.assertNotSame; 2242e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikasimport static org.junit.Assert.assertTrue; 2342e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas 24121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyarimport android.content.Context; 25121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyarimport android.graphics.Canvas; 26121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyarimport android.util.AttributeSet; 27121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyarimport android.util.Log; 28121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyarimport android.view.View; 29121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 30121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyarimport java.util.ArrayList; 31121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyarimport java.util.HashSet; 32121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyarimport java.util.List; 33121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyarimport java.util.Set; 34121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyarimport java.util.concurrent.CountDownLatch; 35121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyarimport java.util.concurrent.TimeUnit; 36121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 37121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar/** 38121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar * Base class for animation related tests. 39121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar */ 40121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyarpublic class BaseRecyclerViewAnimationsTest extends BaseRecyclerViewInstrumentationTest { 41121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 42959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar protected static final boolean DEBUG = false; 43121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 44121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar protected static final String TAG = "RecyclerViewAnimationsTest"; 45121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 46121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar AnimationLayoutManager mLayoutManager; 47121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 48121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar TestAdapter mTestAdapter; 49121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 50121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar public BaseRecyclerViewAnimationsTest() { 51121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar super(DEBUG); 52121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 53121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 54121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar RecyclerView setupBasic(int itemCount) throws Throwable { 55121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar return setupBasic(itemCount, 0, itemCount); 56121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 57121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 58121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar RecyclerView setupBasic(int itemCount, int firstLayoutStartIndex, int firstLayoutItemCount) 59121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar throws Throwable { 60121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar return setupBasic(itemCount, firstLayoutStartIndex, firstLayoutItemCount, null); 61121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 62121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 63121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar RecyclerView setupBasic(int itemCount, int firstLayoutStartIndex, int firstLayoutItemCount, 64121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar TestAdapter testAdapter) 65121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar throws Throwable { 66121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar final TestRecyclerView recyclerView = new TestRecyclerView(getActivity()); 67121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar recyclerView.setHasFixedSize(true); 68121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar if (testAdapter == null) { 69121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar mTestAdapter = new TestAdapter(itemCount); 70121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } else { 71121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar mTestAdapter = testAdapter; 72121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 73121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar recyclerView.setAdapter(mTestAdapter); 74121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar recyclerView.setItemAnimator(createItemAnimator()); 75121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar mLayoutManager = new AnimationLayoutManager(); 76121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar recyclerView.setLayoutManager(mLayoutManager); 77121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar mLayoutManager.mOnLayoutCallbacks.mLayoutMin = firstLayoutStartIndex; 78121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar mLayoutManager.mOnLayoutCallbacks.mLayoutItemCount = firstLayoutItemCount; 79121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 80121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar mLayoutManager.expectLayouts(1); 81121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar recyclerView.expectDraw(1); 82121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar setRecyclerView(recyclerView); 83121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar mLayoutManager.waitForLayout(2); 84121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar recyclerView.waitForDraw(1); 85121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar mLayoutManager.mOnLayoutCallbacks.reset(); 86121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar getInstrumentation().waitForIdleSync(); 87e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar checkForMainThreadException(); 88121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar assertEquals("extra layouts should not happen", 1, mLayoutManager.getTotalLayoutCount()); 89121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar assertEquals("all expected children should be laid out", firstLayoutItemCount, 90121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar mLayoutManager.getChildCount()); 91121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar return recyclerView; 92121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 93121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 94121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar protected RecyclerView.ItemAnimator createItemAnimator() { 95121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar return new DefaultItemAnimator(); 96121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 97121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 98121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar public TestRecyclerView getTestRecyclerView() { 99121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar return (TestRecyclerView) mRecyclerView; 100121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 101121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 102121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar class AnimationLayoutManager extends TestLayoutManager { 103121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 104121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar protected int mTotalLayoutCount = 0; 105121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar private String log; 106121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 107121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar OnLayoutCallbacks mOnLayoutCallbacks = new OnLayoutCallbacks() { 108121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar }; 109121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 110121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 111121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 112121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar @Override 113121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar public boolean supportsPredictiveItemAnimations() { 114121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar return true; 115121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 116121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 117121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar public String getLog() { 118121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar return log; 119121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 120121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 121121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar private String prepareLog(RecyclerView.Recycler recycler, RecyclerView.State state, boolean done) { 122121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar StringBuilder builder = new StringBuilder(); 123121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar builder.append("is pre layout:").append(state.isPreLayout()).append(", done:").append(done); 124121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar builder.append("\nViewHolders:\n"); 125121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar for (RecyclerView.ViewHolder vh : ((TestRecyclerView)mRecyclerView).collectViewHolders()) { 126121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar builder.append(vh).append("\n"); 127121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 128121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar builder.append("scrap:\n"); 129121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar for (RecyclerView.ViewHolder vh : recycler.getScrapList()) { 130121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar builder.append(vh).append("\n"); 131121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 132121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 133121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar if (state.isPreLayout() && !done) { 134121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar log = "\n" + builder.toString(); 135121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } else { 136121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar log += "\n" + builder.toString(); 137121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 138121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar return log; 139121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 140121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 141121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar @Override 142121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar public void expectLayouts(int count) { 143121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar super.expectLayouts(count); 144121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar mOnLayoutCallbacks.mLayoutCount = 0; 145121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 146121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 147121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar public void setOnLayoutCallbacks(OnLayoutCallbacks onLayoutCallbacks) { 148121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar mOnLayoutCallbacks = onLayoutCallbacks; 149121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 150121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 151121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar @Override 152121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar public final void onLayoutChildren(RecyclerView.Recycler recycler, 153121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar RecyclerView.State state) { 154121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar try { 155121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar mTotalLayoutCount++; 156121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar prepareLog(recycler, state, false); 157121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar if (state.isPreLayout()) { 158121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar validateOldPositions(recycler, state); 159121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } else { 160121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar validateClearedOldPositions(recycler, state); 161121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 162121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar mOnLayoutCallbacks.onLayoutChildren(recycler, this, state); 163121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar prepareLog(recycler, state, true); 164121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } finally { 165121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar layoutLatch.countDown(); 166121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 167121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 168121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 169121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar private void validateClearedOldPositions(RecyclerView.Recycler recycler, 170121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar RecyclerView.State state) { 171121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar if (getTestRecyclerView() == null) { 172121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar return; 173121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 174121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar for (RecyclerView.ViewHolder viewHolder : getTestRecyclerView().collectViewHolders()) { 175121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar assertEquals("there should NOT be an old position in post layout", 176121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar RecyclerView.NO_POSITION, viewHolder.mOldPosition); 177121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar assertEquals("there should NOT be a pre layout position in post layout", 178121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar RecyclerView.NO_POSITION, viewHolder.mPreLayoutPosition); 179121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 180121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 181121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 182121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar private void validateOldPositions(RecyclerView.Recycler recycler, 183121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar RecyclerView.State state) { 184121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar if (getTestRecyclerView() == null) { 185121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar return; 186121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 187121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar for (RecyclerView.ViewHolder viewHolder : getTestRecyclerView().collectViewHolders()) { 188121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar if (!viewHolder.isRemoved() && !viewHolder.isInvalid()) { 189121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar assertTrue("there should be an old position in pre-layout", 190121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar viewHolder.mOldPosition != RecyclerView.NO_POSITION); 191121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 192121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 193121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 194121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 195121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar public int getTotalLayoutCount() { 196121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar return mTotalLayoutCount; 197121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 198121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 199121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar @Override 200121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar public boolean canScrollVertically() { 201121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar return true; 202121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 203121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 204121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar @Override 205121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, 206121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar RecyclerView.State state) { 207121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar mOnLayoutCallbacks.onScroll(dy, recycler, state); 208121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar return super.scrollVerticallyBy(dy, recycler, state); 209121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 210121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 211121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar public void onPostDispatchLayout() { 212121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar mOnLayoutCallbacks.postDispatchLayout(); 213121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 214121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 215121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 216121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar abstract class OnLayoutCallbacks { 217121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 218121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar int mLayoutMin = Integer.MIN_VALUE; 219121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 220121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar int mLayoutItemCount = Integer.MAX_VALUE; 221121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 222121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar int expectedPreLayoutItemCount = -1; 223121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 224121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar int expectedPostLayoutItemCount = -1; 225121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 226121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar int mDeletedViewCount; 227121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 228121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar int mLayoutCount = 0; 229121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 230121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar void setExpectedItemCounts(int preLayout, int postLayout) { 231121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar expectedPreLayoutItemCount = preLayout; 232121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar expectedPostLayoutItemCount = postLayout; 233121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 234121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 235121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar void reset() { 236121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar mLayoutMin = Integer.MIN_VALUE; 237121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar mLayoutItemCount = Integer.MAX_VALUE; 238121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar expectedPreLayoutItemCount = -1; 239121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar expectedPostLayoutItemCount = -1; 240121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar mLayoutCount = 0; 241121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 242121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 243121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar void beforePreLayout(RecyclerView.Recycler recycler, 244121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar AnimationLayoutManager lm, RecyclerView.State state) { 245121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar mDeletedViewCount = 0; 246121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar for (int i = 0; i < lm.getChildCount(); i++) { 247121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar View v = lm.getChildAt(i); 248121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar if (lm.getLp(v).isItemRemoved()) { 249121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar mDeletedViewCount++; 250121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 251121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 252121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 253121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 254121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar void doLayout(RecyclerView.Recycler recycler, AnimationLayoutManager lm, 255121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar RecyclerView.State state) { 256121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar if (DEBUG) { 257121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar Log.d(TAG, "item count " + state.getItemCount()); 258121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 259121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar lm.detachAndScrapAttachedViews(recycler); 260121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar final int start = mLayoutMin == Integer.MIN_VALUE ? 0 : mLayoutMin; 261121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar final int count = mLayoutItemCount 262121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar == Integer.MAX_VALUE ? state.getItemCount() : mLayoutItemCount; 263121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar lm.layoutRange(recycler, start, start + count); 264121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar assertEquals("correct # of children should be laid out", 265121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar count, lm.getChildCount()); 266121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar lm.assertVisibleItemPositions(); 267121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 268121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 269121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar private void assertNoPreLayoutPosition(RecyclerView.Recycler recycler) { 270121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar for (RecyclerView.ViewHolder vh : recycler.mAttachedScrap) { 271121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar assertPreLayoutPosition(vh); 272121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 273121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 274121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 275121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar private void assertNoPreLayoutPosition(RecyclerView.LayoutManager lm) { 276121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar for (int i = 0; i < lm.getChildCount(); i ++) { 277121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar final RecyclerView.ViewHolder vh = mRecyclerView 278121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar .getChildViewHolder(lm.getChildAt(i)); 279121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar assertPreLayoutPosition(vh); 280121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 281121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 282121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 283121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar private void assertPreLayoutPosition(RecyclerView.ViewHolder vh) { 284121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar assertEquals("in post layout, there should not be a view holder w/ a pre " 285121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar + "layout position", RecyclerView.NO_POSITION, vh.mPreLayoutPosition); 286121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar assertEquals("in post layout, there should not be a view holder w/ an old " 287121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar + "layout position", RecyclerView.NO_POSITION, vh.mOldPosition); 288121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 289121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 290121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar void onLayoutChildren(RecyclerView.Recycler recycler, AnimationLayoutManager lm, 291121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar RecyclerView.State state) { 292121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar if (state.isPreLayout()) { 293121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar if (expectedPreLayoutItemCount != -1) { 294121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar assertEquals("on pre layout, state should return abstracted adapter size", 295121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar expectedPreLayoutItemCount, state.getItemCount()); 296121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 297121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar beforePreLayout(recycler, lm, state); 298121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } else { 299121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar if (expectedPostLayoutItemCount != -1) { 300121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar assertEquals("on post layout, state should return real adapter size", 301121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar expectedPostLayoutItemCount, state.getItemCount()); 302121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 303121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar beforePostLayout(recycler, lm, state); 304121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 305121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar if (!state.isPreLayout()) { 306121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar assertNoPreLayoutPosition(recycler); 307121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 308121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar doLayout(recycler, lm, state); 309121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar if (state.isPreLayout()) { 310121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar afterPreLayout(recycler, lm, state); 311121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } else { 312121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar afterPostLayout(recycler, lm, state); 313121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar assertNoPreLayoutPosition(lm); 314121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 315121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar mLayoutCount++; 316121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 317121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 318121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar void afterPreLayout(RecyclerView.Recycler recycler, AnimationLayoutManager layoutManager, 319121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar RecyclerView.State state) { 320121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 321121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 322121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar void beforePostLayout(RecyclerView.Recycler recycler, AnimationLayoutManager layoutManager, 323121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar RecyclerView.State state) { 324121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 325121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 326121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar void afterPostLayout(RecyclerView.Recycler recycler, AnimationLayoutManager layoutManager, 327121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar RecyclerView.State state) { 328121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 329121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 330121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar void postDispatchLayout() { 331121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 332121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 333121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar public void onScroll(int dx, RecyclerView.Recycler recycler, RecyclerView.State state) { 334121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 335121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 336121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 337121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 338121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar class TestRecyclerView extends RecyclerView { 339121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 340121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar CountDownLatch drawLatch; 341121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 342121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar public TestRecyclerView(Context context) { 343121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar super(context); 344121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 345121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 346121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar public TestRecyclerView(Context context, AttributeSet attrs) { 347121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar super(context, attrs); 348121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 349121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 350121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar public TestRecyclerView(Context context, AttributeSet attrs, int defStyle) { 351121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar super(context, attrs, defStyle); 352121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 353121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 354121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar @Override 355121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar void initAdapterManager() { 356121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar super.initAdapterManager(); 357121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar mAdapterHelper.mOnItemProcessedCallback = new Runnable() { 358121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar @Override 359121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar public void run() { 360121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar validatePostUpdateOp(); 361121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 362121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar }; 363121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 364121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 365121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar @Override 366121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar boolean isAccessibilityEnabled() { 367121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar return true; 368121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 369121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 370121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar public void expectDraw(int count) { 371121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar drawLatch = new CountDownLatch(count); 372121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 373121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 374121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar public void waitForDraw(long timeout) throws Throwable { 375121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar drawLatch.await(timeout * (DEBUG ? 100 : 1), TimeUnit.SECONDS); 376121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar assertEquals("all expected draws should happen at the expected time frame", 377121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 0, drawLatch.getCount()); 378121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 379121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 380121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar List<ViewHolder> collectViewHolders() { 381121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar List<ViewHolder> holders = new ArrayList<ViewHolder>(); 382121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar final int childCount = getChildCount(); 383121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar for (int i = 0; i < childCount; i++) { 384121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar ViewHolder holder = getChildViewHolderInt(getChildAt(i)); 385121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar if (holder != null) { 386121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar holders.add(holder); 387121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 388121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 389121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar return holders; 390121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 391121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 392121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 393121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar private void validateViewHolderPositions() { 394121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar final Set<Integer> existingOffsets = new HashSet<Integer>(); 395121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar int childCount = getChildCount(); 396121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar StringBuilder log = new StringBuilder(); 397121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar for (int i = 0; i < childCount; i++) { 398121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar ViewHolder vh = getChildViewHolderInt(getChildAt(i)); 399121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar TestViewHolder tvh = (TestViewHolder) vh; 400121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar log.append(tvh.mBoundItem).append(vh) 401121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar .append(" hidden:") 402121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar .append(mChildHelper.mHiddenViews.contains(vh.itemView)) 403121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar .append("\n"); 404121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 405121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar for (int i = 0; i < childCount; i++) { 406121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar ViewHolder vh = getChildViewHolderInt(getChildAt(i)); 407121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar if (vh.isInvalid()) { 408121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar continue; 409121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 410121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar if (vh.getLayoutPosition() < 0) { 411121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar LayoutManager lm = getLayoutManager(); 412121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar for (int j = 0; j < lm.getChildCount(); j ++) { 413121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar assertNotSame("removed view holder should not be in LM's child list", 414121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar vh.itemView, lm.getChildAt(j)); 415121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 416121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } else if (!mChildHelper.mHiddenViews.contains(vh.itemView)) { 417121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar if (!existingOffsets.add(vh.getLayoutPosition())) { 418121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar throw new IllegalStateException("view holder position conflict for " 419121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar + "existing views " + vh + "\n" + log); 420121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 421121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 422121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 423121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 424121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 425121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar void validatePostUpdateOp() { 426121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar try { 427121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar validateViewHolderPositions(); 428121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar if (super.mState.isPreLayout()) { 429121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar validatePreLayoutSequence((AnimationLayoutManager) getLayoutManager()); 430121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 431121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar validateAdapterPosition((AnimationLayoutManager) getLayoutManager()); 432121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } catch (Throwable t) { 433121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar postExceptionToInstrumentation(t); 434121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 435121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 436121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 437121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 438121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 439121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar private void validateAdapterPosition(AnimationLayoutManager lm) { 440121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar for (ViewHolder vh : collectViewHolders()) { 441121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar if (!vh.isRemoved() && vh.mPreLayoutPosition >= 0) { 442121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar assertEquals("adapter position calculations should match view holder " 443121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar + "pre layout:" + mState.isPreLayout() 444121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar + " positions\n" + vh + "\n" + lm.getLog(), 445121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar mAdapterHelper.findPositionOffset(vh.mPreLayoutPosition), vh.mPosition); 446121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 447121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 448121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 449121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 450121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar // ensures pre layout positions are continuous block. This is not necessarily a case 451121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar // but valid in test RV 452121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar private void validatePreLayoutSequence(AnimationLayoutManager lm) { 453121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar Set<Integer> preLayoutPositions = new HashSet<Integer>(); 454121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar for (ViewHolder vh : collectViewHolders()) { 455121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar assertTrue("pre layout positions should be distinct " + lm.getLog(), 456121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar preLayoutPositions.add(vh.mPreLayoutPosition)); 457121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 458121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar int minPos = Integer.MAX_VALUE; 459121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar for (Integer pos : preLayoutPositions) { 460121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar if (pos < minPos) { 461121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar minPos = pos; 462121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 463121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 464121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar for (int i = 1; i < preLayoutPositions.size(); i++) { 465121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar assertNotNull("next position should exist " + lm.getLog(), 466121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar preLayoutPositions.contains(minPos + i)); 467121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 468121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 469121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 470121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar @Override 471121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar protected void dispatchDraw(Canvas canvas) { 472121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar super.dispatchDraw(canvas); 473121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar if (drawLatch != null) { 474121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar drawLatch.countDown(); 475121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 476121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 477121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 478121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar @Override 479121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar void dispatchLayout() { 480121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar try { 481121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar super.dispatchLayout(); 482121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar if (getLayoutManager() instanceof AnimationLayoutManager) { 483121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar ((AnimationLayoutManager) getLayoutManager()).onPostDispatchLayout(); 484121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 485121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } catch (Throwable t) { 486121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar postExceptionToInstrumentation(t); 487121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 488121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 489121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 490121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 491121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 492121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 493121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 494121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar abstract class AdapterOps { 495121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 496121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar final public void run(TestAdapter adapter) throws Throwable { 497121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar onRun(adapter); 498121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 499121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 500121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar abstract void onRun(TestAdapter testAdapter) throws Throwable; 501121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 502121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 503121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar static class CollectPositionResult { 504121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 505121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar // true if found in scrap 506121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar public RecyclerView.ViewHolder scrapResult; 507121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 508121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar public RecyclerView.ViewHolder adapterResult; 509121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 510121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar static CollectPositionResult fromScrap(RecyclerView.ViewHolder viewHolder) { 511121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar CollectPositionResult cpr = new CollectPositionResult(); 512121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar cpr.scrapResult = viewHolder; 513121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar return cpr; 514121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 515121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 516121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar static CollectPositionResult fromAdapter(RecyclerView.ViewHolder viewHolder) { 517121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar CollectPositionResult cpr = new CollectPositionResult(); 518121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar cpr.adapterResult = viewHolder; 519121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar return cpr; 520121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 521121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 522121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar @Override 523121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar public String toString() { 524121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar return "CollectPositionResult{" + 525121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar "scrapResult=" + scrapResult + 526121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar ", adapterResult=" + adapterResult + 527121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar '}'; 528121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 529121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 530121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 531121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar static class PositionConstraint { 532121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 533121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar public static enum Type { 534121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar scrap, 535121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar adapter, 536121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar adapterScrap /*first pass adapter, second pass scrap*/ 537121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 538121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 539121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar Type mType; 540121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 541121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar int mOldPos; // if VH 542121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 543121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar int mPreLayoutPos; 544121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 545121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar int mPostLayoutPos; 546121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 547121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar int mValidateCount = 0; 548121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 549121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar public static PositionConstraint scrap(int oldPos, int preLayoutPos, int postLayoutPos) { 550121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar PositionConstraint constraint = new PositionConstraint(); 551121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar constraint.mType = Type.scrap; 552121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar constraint.mOldPos = oldPos; 553121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar constraint.mPreLayoutPos = preLayoutPos; 554121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar constraint.mPostLayoutPos = postLayoutPos; 555121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar return constraint; 556121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 557121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 558121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar public static PositionConstraint adapterScrap(int preLayoutPos, int position) { 559121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar PositionConstraint constraint = new PositionConstraint(); 560121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar constraint.mType = Type.adapterScrap; 561121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar constraint.mOldPos = RecyclerView.NO_POSITION; 562121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar constraint.mPreLayoutPos = preLayoutPos; 563121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar constraint.mPostLayoutPos = position;// adapter pos does not change 564121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar return constraint; 565121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 566121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 567121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar public static PositionConstraint adapter(int position) { 568121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar PositionConstraint constraint = new PositionConstraint(); 569121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar constraint.mType = Type.adapter; 570121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar constraint.mPreLayoutPos = RecyclerView.NO_POSITION; 571121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar constraint.mOldPos = RecyclerView.NO_POSITION; 572121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar constraint.mPostLayoutPos = position;// adapter pos does not change 573121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar return constraint; 574121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 575121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 576121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar public void assertValidate() { 577121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar int expectedValidate = 0; 578121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar if (mPreLayoutPos >= 0) { 579121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar expectedValidate ++; 580121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 581121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar if (mPostLayoutPos >= 0) { 582121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar expectedValidate ++; 583121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 584121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar assertEquals("should run all validates", expectedValidate, mValidateCount); 585121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 586121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 587121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar @Override 588121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar public String toString() { 589121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar return "Cons{" + 590121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar "t=" + mType.name() + 591121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar ", old=" + mOldPos + 592121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar ", pre=" + mPreLayoutPos + 593121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar ", post=" + mPostLayoutPos + 594121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar '}'; 595121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 596121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 597121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar public void validate(RecyclerView.State state, CollectPositionResult result, String log) { 598121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar mValidateCount ++; 599121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar assertNotNull(this + ": result should not be null\n" + log, result); 600121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar RecyclerView.ViewHolder viewHolder; 601121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar if (mType == Type.scrap || (mType == Type.adapterScrap && !state.isPreLayout())) { 602121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar assertNotNull(this + ": result should come from scrap\n" + log, result.scrapResult); 603121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar viewHolder = result.scrapResult; 604121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } else { 605121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar assertNotNull(this + ": result should come from adapter\n" + log, 606121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar result.adapterResult); 607121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar assertEquals(this + ": old position should be none when it came from adapter\n" + log, 608121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar RecyclerView.NO_POSITION, result.adapterResult.getOldPosition()); 609121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar viewHolder = result.adapterResult; 610121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 611121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar if (state.isPreLayout()) { 612121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar assertEquals(this + ": pre-layout position should match\n" + log, mPreLayoutPos, 613121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar viewHolder.mPreLayoutPosition == -1 ? viewHolder.mPosition : 614121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar viewHolder.mPreLayoutPosition); 615121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar assertEquals(this + ": pre-layout getPosition should match\n" + log, mPreLayoutPos, 616121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar viewHolder.getLayoutPosition()); 617121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar if (mType == Type.scrap) { 618121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar assertEquals(this + ": old position should match\n" + log, mOldPos, 619121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar result.scrapResult.getOldPosition()); 620121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 621121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } else if (mType == Type.adapter || mType == Type.adapterScrap || !result.scrapResult 622121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar .isRemoved()) { 623121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar assertEquals(this + ": post-layout position should match\n" + log + "\n\n" 624121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar + viewHolder, mPostLayoutPos, viewHolder.getLayoutPosition()); 625121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 626121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 627121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar } 6289051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar 6299051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar static class LoggingInfo extends RecyclerView.ItemAnimator.ItemHolderInfo { 6309051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar final RecyclerView.ViewHolder viewHolder; 6319051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar @RecyclerView.ItemAnimator.AdapterChanges 6329051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar final int changeFlags; 6339051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar final List<Object> payloads; 6349051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar 6359051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar LoggingInfo(RecyclerView.ViewHolder viewHolder, int changeFlags, List<Object> payloads) { 6369051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar this.viewHolder = viewHolder; 6379051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar this.changeFlags = changeFlags; 6389051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar if (payloads != null) { 6399051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar this.payloads = new ArrayList<>(); 6409051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar this.payloads.addAll(payloads); 6419051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar } else { 6429051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar this.payloads = null; 6439051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar } 6449051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar setFrom(viewHolder); 6459051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar } 6464143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar 6474143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar @Override 6484143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar public String toString() { 6494143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar return "LoggingInfo{" + 6504143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar "changeFlags=" + changeFlags + 6514143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar ", payloads=" + payloads + 6524143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar '}'; 6534143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar } 6549051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar } 6559051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar 656e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar static class AnimateChange extends AnimateLogBase { 6579051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar 6589051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar final RecyclerView.ViewHolder newHolder; 6599051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar 6609051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar public AnimateChange(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder, 6619051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar LoggingInfo pre, LoggingInfo post) { 6629051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar super(oldHolder, pre, post); 6639051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar this.newHolder = newHolder; 6649051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar } 6659051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar } 6669051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar 667e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar static class AnimatePersistence extends AnimateLogBase { 6689051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar 6699051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar public AnimatePersistence(RecyclerView.ViewHolder viewHolder, LoggingInfo pre, 6709051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar LoggingInfo post) { 6719051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar super(viewHolder, pre, post); 6729051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar } 6739051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar } 6749051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar 675e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar static class AnimateAppearance extends AnimateLogBase { 6769051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar public AnimateAppearance(RecyclerView.ViewHolder viewHolder, LoggingInfo pre, 6779051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar LoggingInfo post) { 678e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar super(viewHolder, pre, post); 6799051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar } 6809051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar } 6819051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar 6829051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar static class AnimateDisappearance extends AnimateLogBase { 683e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar public AnimateDisappearance(RecyclerView.ViewHolder viewHolder, LoggingInfo pre, 684e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar LoggingInfo post) { 685e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar super(viewHolder, pre, post); 6869051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar } 6879051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar } 6889051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar static class AnimateLogBase { 6899051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar 6904143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar public final RecyclerView.ViewHolder viewHolder; 6914143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar public final LoggingInfo preInfo; 6924143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar public final LoggingInfo postInfo; 6939051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar 694e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar public AnimateLogBase(RecyclerView.ViewHolder viewHolder, LoggingInfo pre, 695e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar LoggingInfo postInfo) { 6969051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar this.viewHolder = viewHolder; 6979051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar this.preInfo = pre; 698e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar this.postInfo = postInfo; 699e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar } 700e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar 7014143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar public String log() { 7024143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar return getClass().getSimpleName() + "[" + log(preInfo) + " - " + log(postInfo) + "]"; 7034143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar } 7044143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar 7054143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar public String log(LoggingInfo info) { 7064143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar return info == null ? "null" : info.toString(); 7074143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar } 7084143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar 709e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar @Override 710e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar public boolean equals(Object o) { 711e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar if (this == o) { 712e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar return true; 713e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar } 714e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar if (o == null || getClass() != o.getClass()) { 715e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar return false; 716e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar } 717e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar 718e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar AnimateLogBase that = (AnimateLogBase) o; 719e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar 720e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar if (viewHolder != null ? !viewHolder.equals(that.viewHolder) 721e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar : that.viewHolder != null) { 722e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar return false; 723e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar } 724e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar if (preInfo != null ? !preInfo.equals(that.preInfo) : that.preInfo != null) { 725e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar return false; 726e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar } 727e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar return !(postInfo != null ? !postInfo.equals(that.postInfo) : that.postInfo != null); 728e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar 729e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar } 730e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar 731e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar @Override 732e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar public int hashCode() { 733e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar int result = viewHolder != null ? viewHolder.hashCode() : 0; 734e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar result = 31 * result + (preInfo != null ? preInfo.hashCode() : 0); 735e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar result = 31 * result + (postInfo != null ? postInfo.hashCode() : 0); 736e09e0b4ea04b6b6b0ef6c62979e8abdead0bf378Yigit Boyar return result; 7379051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar } 7389051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar } 739121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar} 740