RecyclerViewAnimationsTest.java revision e0c347f627f8a78d3e5e3e5eaac9c3ae26208689
1d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase/* 2d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * Copyright (C) 2014 The Android Open Source Project 3d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * 4d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * Licensed under the Apache License, Version 2.0 (the "License"); 5d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * you may not use this file except in compliance with the License. 6d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * You may obtain a copy of the License at 7d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * 8d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * http://www.apache.org/licenses/LICENSE-2.0 9d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * 10d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * Unless required by applicable law or agreed to in writing, software 11d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * distributed under the License is distributed on an "AS IS" BASIS, 12d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * See the License for the specific language governing permissions and 14d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * limitations under the License. 15d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase */ 16d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 17d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haasepackage android.support.v7.widget; 18d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 19b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyarimport android.content.Context; 20888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyarimport android.graphics.Canvas; 21b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyarimport android.util.AttributeSet; 22b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyarimport android.util.Log; 23b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyarimport android.view.View; 24b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 2511b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyarimport java.util.ArrayList; 268ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyarimport java.util.HashMap; 2711b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyarimport java.util.HashSet; 2811b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyarimport java.util.List; 2911b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyarimport java.util.Map; 3011b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyarimport java.util.Set; 31888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyarimport java.util.concurrent.CountDownLatch; 32d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haaseimport java.util.concurrent.TimeUnit; 33d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyarimport java.util.concurrent.atomic.AtomicInteger; 34d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 35d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haasepublic class RecyclerViewAnimationsTest extends BaseRecyclerViewInstrumentationTest { 36d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 37668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar private static final boolean DEBUG = false; 38b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 39b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar private static final String TAG = "RecyclerViewAnimationsTest"; 40b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 41b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar AnimationLayoutManager mLayoutManager; 42b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 43b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar TestAdapter mTestAdapter; 44b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 45b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar public RecyclerViewAnimationsTest() { 46b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar super(DEBUG); 47b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 48b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 49b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar @Override 50b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar protected void setUp() throws Exception { 51b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar super.setUp(); 52b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 53b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 54b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar RecyclerView setupBasic(int itemCount) throws Throwable { 55b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar return setupBasic(itemCount, 0, itemCount); 56b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 57b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 58b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar RecyclerView setupBasic(int itemCount, int firstLayoutStartIndex, int firstLayoutItemCount) 59b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar throws Throwable { 6011b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar return setupBasic(itemCount, firstLayoutStartIndex, firstLayoutItemCount, null); 6111b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar } 6211b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar 6311b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar RecyclerView setupBasic(int itemCount, int firstLayoutStartIndex, int firstLayoutItemCount, 6411b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar TestAdapter testAdapter) 6511b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar throws Throwable { 66888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar final TestRecyclerView recyclerView = new TestRecyclerView(getActivity()); 67b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar recyclerView.setHasFixedSize(true); 6811b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar if (testAdapter == null) { 6911b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar mTestAdapter = new TestAdapter(itemCount); 7011b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar } else { 7111b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar mTestAdapter = testAdapter; 7211b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar } 73b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar recyclerView.setAdapter(mTestAdapter); 74b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar mLayoutManager = new AnimationLayoutManager(); 75b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar recyclerView.setLayoutManager(mLayoutManager); 76b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar mLayoutManager.mOnLayoutCallbacks.mLayoutMin = firstLayoutStartIndex; 77b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar mLayoutManager.mOnLayoutCallbacks.mLayoutItemCount = firstLayoutItemCount; 78b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 79b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar mLayoutManager.expectLayouts(1); 80888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar recyclerView.expectDraw(1); 81b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar setRecyclerView(recyclerView); 82b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar mLayoutManager.waitForLayout(2); 83888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar recyclerView.waitForDraw(1); 84888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar mLayoutManager.mOnLayoutCallbacks.reset(); 858ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar getInstrumentation().waitForIdleSync(); 86b7b44e5454dc409934bcc5609b81d1715c984d40Yigit Boyar assertEquals("extra layouts should not happen", 1, mLayoutManager.getTotalLayoutCount()); 878ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar assertEquals("all expected children should be laid out", firstLayoutItemCount, 888ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar mLayoutManager.getChildCount()); 89b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar return recyclerView; 90b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 91b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 92b7b44e5454dc409934bcc5609b81d1715c984d40Yigit Boyar public void testNotifyDataSetChanged() throws Throwable { 93b7b44e5454dc409934bcc5609b81d1715c984d40Yigit Boyar setupBasic(10, 3, 4); 94b7b44e5454dc409934bcc5609b81d1715c984d40Yigit Boyar int layoutCount = mLayoutManager.mTotalLayoutCount; 95b7b44e5454dc409934bcc5609b81d1715c984d40Yigit Boyar mLayoutManager.expectLayouts(1); 96b7b44e5454dc409934bcc5609b81d1715c984d40Yigit Boyar runTestOnUiThread(new Runnable() { 97b7b44e5454dc409934bcc5609b81d1715c984d40Yigit Boyar @Override 98b7b44e5454dc409934bcc5609b81d1715c984d40Yigit Boyar public void run() { 99b7b44e5454dc409934bcc5609b81d1715c984d40Yigit Boyar try { 100b7b44e5454dc409934bcc5609b81d1715c984d40Yigit Boyar mTestAdapter.deleteAndNotify(4, 1); 101b7b44e5454dc409934bcc5609b81d1715c984d40Yigit Boyar mTestAdapter.notifyChange(); 102b7b44e5454dc409934bcc5609b81d1715c984d40Yigit Boyar } catch (Throwable throwable) { 103b7b44e5454dc409934bcc5609b81d1715c984d40Yigit Boyar throwable.printStackTrace(); 104b7b44e5454dc409934bcc5609b81d1715c984d40Yigit Boyar } 105b7b44e5454dc409934bcc5609b81d1715c984d40Yigit Boyar 106b7b44e5454dc409934bcc5609b81d1715c984d40Yigit Boyar } 107b7b44e5454dc409934bcc5609b81d1715c984d40Yigit Boyar }); 108b7b44e5454dc409934bcc5609b81d1715c984d40Yigit Boyar mLayoutManager.waitForLayout(2); 109b7b44e5454dc409934bcc5609b81d1715c984d40Yigit Boyar getInstrumentation().waitForIdleSync(); 110b7b44e5454dc409934bcc5609b81d1715c984d40Yigit Boyar assertEquals("on notify data set changed, predictive animations should not run", 111b7b44e5454dc409934bcc5609b81d1715c984d40Yigit Boyar layoutCount + 1, mLayoutManager.mTotalLayoutCount); 112b7b44e5454dc409934bcc5609b81d1715c984d40Yigit Boyar mLayoutManager.expectLayouts(2); 113b7b44e5454dc409934bcc5609b81d1715c984d40Yigit Boyar mTestAdapter.addAndNotify(4, 2); 114b7b44e5454dc409934bcc5609b81d1715c984d40Yigit Boyar // make sure animations recover 115b7b44e5454dc409934bcc5609b81d1715c984d40Yigit Boyar mLayoutManager.waitForLayout(2); 116b7b44e5454dc409934bcc5609b81d1715c984d40Yigit Boyar } 117b7b44e5454dc409934bcc5609b81d1715c984d40Yigit Boyar 118e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar public void testStableIdNotifyDataSetChanged() throws Throwable { 119e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar final int itemCount = 20; 120e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar List<Item> initialSet = new ArrayList<Item>(); 121e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar final TestAdapter adapter = new TestAdapter(itemCount) { 122e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar @Override 123e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar public long getItemId(int position) { 124e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar return mItems.get(position).mId; 125e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar } 126e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar }; 127e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar adapter.setHasStableIds(true); 128e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar initialSet.addAll(adapter.mItems); 129e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar positionStatesTest(itemCount, 5, 5, adapter, new AdapterOps() { 130e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar @Override 131e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar void onRun(TestAdapter testAdapter) throws Throwable { 132e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar Item item5 = adapter.mItems.get(5); 133e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar Item item6 = adapter.mItems.get(6); 134e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar item5.mAdapterIndex = 6; 135e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar item6.mAdapterIndex = 5; 136e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar adapter.mItems.remove(5); 137e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar adapter.mItems.add(6, item5); 138e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar adapter.notifyChange(); 139e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar //hacky, we support only 1 layout pass 140e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar mLayoutManager.layoutLatch.countDown(); 141e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar } 142e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar }, PositionConstraint.scrap(6, -1, 5), PositionConstraint.scrap(5, -1, 6), 143e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar PositionConstraint.scrap(7, -1, 7), PositionConstraint.scrap(8, -1, 8), 144e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar PositionConstraint.scrap(9, -1, 9)); 145e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar // now mix items. 146e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar } 147e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar 148d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar 1498ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar public void testGetItemForDeletedView() throws Throwable { 1508ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar getItemForDeletedViewTest(false); 1518ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar getItemForDeletedViewTest(true); 15211b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar } 15311b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar 1548ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar public void getItemForDeletedViewTest(boolean stableIds) throws Throwable { 15511b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar final Set<Integer> itemViewTypeQueries = new HashSet<Integer>(); 15611b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar final Set<Integer> itemIdQueries = new HashSet<Integer>(); 15711b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar TestAdapter adapter = new TestAdapter(10) { 15811b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar @Override 15911b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar public int getItemViewType(int position) { 16011b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar itemViewTypeQueries.add(position); 16111b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar return super.getItemViewType(position); 16211b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar } 16311b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar 16411b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar @Override 16511b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar public long getItemId(int position) { 16611b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar itemIdQueries.add(position); 16711b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar return mItems.get(position).mId; 16811b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar } 16911b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar }; 17011b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar adapter.setHasStableIds(stableIds); 17111b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar setupBasic(10, 0, 10, adapter); 17211b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar assertEquals("getItemViewType for all items should be called", 10, 17311b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar itemViewTypeQueries.size()); 17411b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar if (adapter.hasStableIds()) { 17511b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar assertEquals("getItemId should be called when adapter has stable ids", 10, 17611b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar itemIdQueries.size()); 17711b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar } else { 17811b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar assertEquals("getItemId should not be called when adapter does not have stable ids", 0, 17911b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar itemIdQueries.size()); 18011b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar } 18111b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar itemViewTypeQueries.clear(); 18211b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar itemIdQueries.clear(); 18311b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar mLayoutManager.expectLayouts(2); 18411b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar // delete last two 18511b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar final int deleteStart = 8; 18611b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar final int deleteCount = adapter.getItemCount() - deleteStart; 18711b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar adapter.deleteAndNotify(deleteStart, deleteCount); 18811b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar mLayoutManager.waitForLayout(2); 18911b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar for (int i = 0; i < deleteStart; i++) { 19011b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar assertTrue("getItemViewType for existing item " + i + " should be called", 19111b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar itemViewTypeQueries.contains(i)); 19211b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar if (adapter.hasStableIds()) { 19311b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar assertTrue("getItemId for existing item " + i 19411b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar + " should be called when adapter has stable ids", 19511b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar itemIdQueries.contains(i)); 19611b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar } 19711b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar } 19811b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar for (int i = deleteStart; i < deleteStart + deleteCount; i++) { 19911b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar assertFalse("getItemViewType for deleted item " + i + " SHOULD NOT be called", 20011b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar itemViewTypeQueries.contains(i)); 20111b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar if (adapter.hasStableIds()) { 2028ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar assertFalse("getItemId for deleted item " + i + " SHOULD NOT be called", 20311b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar itemIdQueries.contains(i)); 20411b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar } 20511b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar } 20611b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar } 20711b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar 2088ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar public void testDeleteInvisibleMultiStep() throws Throwable { 2098ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar setupBasic(1000, 1, 7); 2108ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar mLayoutManager.mOnLayoutCallbacks.mLayoutMin = 1; 2118ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar mLayoutManager.mOnLayoutCallbacks.mLayoutItemCount = 7; 2128ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar mLayoutManager.expectLayouts(1); 2138ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar // try to trigger race conditions 2148ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar int targetItemCount = mTestAdapter.getItemCount(); 2158ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar for (int i = 0; i < 100; i++) { 2168ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar mTestAdapter.deleteAndNotify(new int[]{0, 1}, new int[]{7, 1}); 2178ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar targetItemCount -= 2; 2188ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 2198ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar // wait until main thread runnables are consumed 2208ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar while (targetItemCount != mTestAdapter.getItemCount()) { 2218ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar Thread.sleep(100); 2228ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 2238ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar mLayoutManager.waitForLayout(2); 2248ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 2258ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 2268ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar public void testAddManyMultiStep() throws Throwable { 2278ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar setupBasic(10, 1, 7); 2288ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar mLayoutManager.mOnLayoutCallbacks.mLayoutMin = 1; 2298ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar mLayoutManager.mOnLayoutCallbacks.mLayoutItemCount = 7; 2308ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar mLayoutManager.expectLayouts(1); 2318ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar // try to trigger race conditions 2328ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar int targetItemCount = mTestAdapter.getItemCount(); 2338ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar for (int i = 0; i < 100; i++) { 2348ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar mTestAdapter.addAndNotify(0, 1); 2358ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar mTestAdapter.addAndNotify(7, 1); 2368ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar targetItemCount += 2; 2378ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 2388ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar // wait until main thread runnables are consumed 2398ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar while (targetItemCount != mTestAdapter.getItemCount()) { 2408ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar Thread.sleep(100); 2418ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 2428ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar mLayoutManager.waitForLayout(2); 2438ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 2448ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 2458ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar public void testBasicDelete() throws Throwable { 2468ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar setupBasic(10); 2478ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar final OnLayoutCallbacks callbacks = new OnLayoutCallbacks() { 2488ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar @Override 2498ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar public void postDispatchLayout() { 2508ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar // verify this only in first layout 2518ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar assertEquals("deleted views should still be children of RV", 2528ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar mLayoutManager.getChildCount() + mDeletedViewCount 2538ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar , mRecyclerView.getChildCount()); 2548ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 2558ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 2568ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar @Override 2578ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar void afterPreLayout(RecyclerView.Recycler recycler, 2588ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar AnimationLayoutManager layoutManager, 2598ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar RecyclerView.State state) { 2608ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar super.afterPreLayout(recycler, layoutManager, state); 2618ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar mLayoutItemCount = 3; 2628ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar mLayoutMin = 0; 2638ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 2648ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar }; 2658ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar callbacks.mLayoutItemCount = 10; 2668ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar callbacks.setExpectedItemCounts(10, 3); 2678ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar mLayoutManager.setOnLayoutCallbacks(callbacks); 2688ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 2698ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar mLayoutManager.expectLayouts(2); 2708ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar mTestAdapter.deleteAndNotify(0, 7); 2718ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar mLayoutManager.waitForLayout(2); 2728ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar callbacks.reset();// when animations end another layout will happen 2738ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 2748ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 2758ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 276d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar public void testAdapterChangeDuringScrolling() throws Throwable { 277d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar setupBasic(10); 278d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar final AtomicInteger onLayoutItemCount = new AtomicInteger(0); 279d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar final AtomicInteger onScrollItemCount = new AtomicInteger(0); 280d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar 281d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar mLayoutManager.setOnLayoutCallbacks(new OnLayoutCallbacks() { 282d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar @Override 283d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar void onLayoutChildren(RecyclerView.Recycler recycler, 284d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar AnimationLayoutManager lm, RecyclerView.State state) { 285d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar onLayoutItemCount.set(state.getItemCount()); 286d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar super.onLayoutChildren(recycler, lm, state); 287d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar } 288d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar 289d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar @Override 290d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar public void onScroll(int dx, RecyclerView.Recycler recycler, RecyclerView.State state) { 291d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar onScrollItemCount.set(state.getItemCount()); 292d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar super.onScroll(dx, recycler, state); 293d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar } 294d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar }); 295d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar runTestOnUiThread(new Runnable() { 296d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar @Override 297d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar public void run() { 298d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar mTestAdapter.mItems.remove(5); 299d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar mTestAdapter.notifyItemRangeRemoved(5, 1); 300d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar mRecyclerView.scrollBy(0, 100); 301d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar assertTrue("scrolling while there are pending adapter updates should " 302d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar + "trigger a layout", mLayoutManager.mOnLayoutCallbacks.mLayoutCount > 0); 303d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar assertEquals("scroll by should be called w/ updated adapter count", 304d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar mTestAdapter.mItems.size(), onScrollItemCount.get()); 305d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar 306d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar } 307d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar }); 308d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar } 309d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar 310b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar public void testAddInvisibleAndVisible() throws Throwable { 311b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar setupBasic(10, 1, 7); 312b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar mLayoutManager.expectLayouts(2); 313b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar mLayoutManager.mOnLayoutCallbacks.setExpectedItemCounts(10, 12); 3142d2e8d88103866b631eb0f3805da137ebcfb0275Yigit Boyar mTestAdapter.addAndNotify(new int[]{0, 1}, new int[]{7, 1});// add a new item 0 // invisible 315b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar mLayoutManager.waitForLayout(2); 316b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 317b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 318b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar public void testAddInvisible() throws Throwable { 319b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar setupBasic(10, 1, 7); 320b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar mLayoutManager.expectLayouts(1); 321b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar mLayoutManager.mOnLayoutCallbacks.setExpectedItemCounts(10, 12); 3222d2e8d88103866b631eb0f3805da137ebcfb0275Yigit Boyar mTestAdapter.addAndNotify(new int[]{0, 1}, new int[]{8, 1});// add a new item 0 323b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar mLayoutManager.waitForLayout(2); 324b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 325b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 326b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar public void testBasicAdd() throws Throwable { 327b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar setupBasic(10); 328b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar mLayoutManager.expectLayouts(2); 329b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar setExpectedItemCounts(10, 13); 330b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar mTestAdapter.addAndNotify(2, 3); 331b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar mLayoutManager.waitForLayout(2); 332b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 333b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 334888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar public TestRecyclerView getTestRecyclerView() { 335888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar return (TestRecyclerView) mRecyclerView; 336888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar } 337888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar 338888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar public void testRemoveScrapInvalidate() throws Throwable { 339888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar setupBasic(10); 340888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar TestRecyclerView testRecyclerView = getTestRecyclerView(); 341888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar mLayoutManager.expectLayouts(1); 342888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar testRecyclerView.expectDraw(1); 343888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar runTestOnUiThread(new Runnable() { 344888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar @Override 345888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar public void run() { 346888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar mTestAdapter.mItems.clear(); 347888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar mTestAdapter.notifyDataSetChanged(); 348888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar } 349888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar }); 350888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar mLayoutManager.waitForLayout(2); 351888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar testRecyclerView.waitForDraw(2); 352888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar } 353888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar 354b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar public void testDeleteVisibleAndInvisible() throws Throwable { 355b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar setupBasic(11, 3, 5); //layout items 3 4 5 6 7 356b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar mLayoutManager.expectLayouts(2); 3578ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar setLayoutRange(3, 5); //layout previously invisible child 10 from end of the list 358b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar setExpectedItemCounts(9, 8); 359b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar mTestAdapter.deleteAndNotify(new int[]{4, 1}, new int[]{7, 2});// delete items 4, 8, 9 360b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar mLayoutManager.waitForLayout(2); 361b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 362b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 3638ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar public void testFindPositionOffset() throws Throwable { 3648ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar setupBasic(10); 3658ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar runTestOnUiThread(new Runnable() { 3668ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar @Override 3678ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar public void run() { 3688ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar // [0,1,2,3,4] 3698ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar // delete 1 3708ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar mTestAdapter.notifyItemRangeRemoved(1, 1); 3718ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar // delete 3 3728ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar mTestAdapter.notifyItemRangeRemoved(2, 1); 3738ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar mAdapterHelper.preProcess(); 3748ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar // [0,2,4] 3758ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar assertEquals("offset check", 0, mAdapterHelper.findPositionOffset(0)); 3768ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar assertEquals("offset check", 1, mAdapterHelper.findPositionOffset(2)); 3778ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar assertEquals("offset check", 2, mAdapterHelper.findPositionOffset(4)); 3788ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 3798ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 3808ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar }); 3818ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 3828ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 383b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar private void setLayoutRange(int start, int count) { 384b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar mLayoutManager.mOnLayoutCallbacks.mLayoutMin = start; 385b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar mLayoutManager.mOnLayoutCallbacks.mLayoutItemCount = count; 386b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 387b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 388b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar private void setExpectedItemCounts(int preLayout, int postLayout) { 389b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar mLayoutManager.mOnLayoutCallbacks.setExpectedItemCounts(preLayout, postLayout); 390b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 391b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 392b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar public void testDeleteInvisible() throws Throwable { 393b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar setupBasic(10, 1, 7); 3948ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar mLayoutManager.mOnLayoutCallbacks.mLayoutMin = 1; 3958ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar mLayoutManager.mOnLayoutCallbacks.mLayoutItemCount = 7; 396b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar mLayoutManager.expectLayouts(1); 397b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar mLayoutManager.mOnLayoutCallbacks.setExpectedItemCounts(8, 8); 3988ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar mTestAdapter.deleteAndNotify(new int[]{0, 1}, new int[]{7, 1});// delete item id 0,8 399b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar mLayoutManager.waitForLayout(2); 400b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 401b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 402e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar private CollectPositionResult findByPos(RecyclerView recyclerView, 403e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar RecyclerView.Recycler recycler, RecyclerView.State state, int position) { 404e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar View view = recycler.getViewForPosition(position, true); 405e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar RecyclerView.ViewHolder vh = recyclerView.getChildViewHolder(view); 406e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar if (vh.wasReturnedFromScrap()) { 407e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar vh.clearReturnedFromScrapFlag(); //keep data consistent. 408e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar return CollectPositionResult.fromScrap(vh); 409e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar } else { 410e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar return CollectPositionResult.fromAdapter(vh); 4118ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 4128ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 4138ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 414e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar public Map<Integer, CollectPositionResult> collectPositions(RecyclerView recyclerView, 415e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar RecyclerView.Recycler recycler, RecyclerView.State state, int... positions) { 4168ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar Map<Integer, CollectPositionResult> positionToAdapterMapping 4178ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar = new HashMap<Integer, CollectPositionResult>(); 4188ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar for (int position : positions) { 4198ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar if (position < 0) { 4208ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar continue; 4218ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 422e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar positionToAdapterMapping.put(position, 423e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar findByPos(recyclerView, recycler, state, position)); 4248ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 4258ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar return positionToAdapterMapping; 4268ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 4278ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 4288ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar public void testAddDelete2() throws Throwable { 4298ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar positionStatesTest(5, 0, 5, new AdapterOps() { 4308ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar // 0 1 2 3 4 4318ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar // 0 1 2 a b 3 4 4328ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar // 0 1 b 3 4 4338ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar // pre: 0 1 2 3 4 4348ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar // pre w/ adap: 0 1 2 b 3 4 435d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 4368ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar void onRun(TestAdapter adapter) throws Throwable { 4378ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar adapter.addDeleteAndNotify(new int[]{3, 2}, new int[]{2, -2}); 438b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 4398ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar }, PositionConstraint.scrap(2, 2, -1), PositionConstraint.scrap(1, 1, 1), 4408ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar PositionConstraint.scrap(3, 3, 3) 4418ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar ); 4428ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 443d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 4448ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar public void testAddDelete1() throws Throwable { 4458ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar positionStatesTest(5, 0, 5, new AdapterOps() { 4468ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar // 0 1 2 3 4 4478ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar // 0 1 2 a b 3 4 4488ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar // 0 2 a b 3 4 4498ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar // 0 c d 2 a b 3 4 4508ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar // 0 c d 2 a 4 4518ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar // c d 2 a 4 4528ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar // pre: 0 1 2 3 4 453b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar @Override 4548ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar void onRun(TestAdapter adapter) throws Throwable { 4558ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar adapter.addDeleteAndNotify(new int[]{3, 2}, new int[]{1, -1}, 4568ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar new int[]{1, 2}, new int[]{5, -2}, new int[]{0, -1}); 457d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 4588ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar }, PositionConstraint.scrap(0, 0, -1), PositionConstraint.scrap(1, 1, -1), 4598ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar PositionConstraint.scrap(2, 2, 2), PositionConstraint.scrap(3, 3, -1), 4608ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar PositionConstraint.scrap(4, 4, 4), PositionConstraint.adapter(0), 4618ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar PositionConstraint.adapter(1), PositionConstraint.adapter(3) 4628ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar ); 4638ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 4648ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 4658ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar public void testAddSameIndexTwice() throws Throwable { 4668ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar positionStatesTest(12, 2, 7, new AdapterOps() { 4678ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar @Override 4688ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar void onRun(TestAdapter adapter) throws Throwable { 4698ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar adapter.addAndNotify(new int[]{1, 2}, new int[]{5, 1}, new int[]{5, 1}, 4708ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar new int[]{11, 1}); 4718ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 4728ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar }, PositionConstraint.adapterScrap(0, 0), PositionConstraint.adapterScrap(1, 3), 4738ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar PositionConstraint.scrap(2, 2, 4), PositionConstraint.scrap(3, 3, 7), 4748ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar PositionConstraint.scrap(4, 4, 8), PositionConstraint.scrap(7, 7, 12), 4758ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar PositionConstraint.scrap(8, 8, 13) 4768ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar ); 4778ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 4788ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 4798ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar public void testDeleteTwice() throws Throwable { 4808ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar positionStatesTest(12, 2, 7, new AdapterOps() { 4818ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar @Override 4828ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar void onRun(TestAdapter adapter) throws Throwable { 4838ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar adapter.deleteAndNotify(new int[]{0, 1}, new int[]{1, 1}, new int[]{7, 1}, 4848ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar new int[]{0, 1});// delete item ids 0,2,9,1 4858ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 4868ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar }, PositionConstraint.scrap(2, 0, -1), PositionConstraint.scrap(3, 1, 0), 4878ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar PositionConstraint.scrap(4, 2, 1), PositionConstraint.scrap(5, 3, 2), 4888ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar PositionConstraint.scrap(6, 4, 3), PositionConstraint.scrap(8, 6, 5), 4898ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar PositionConstraint.adapterScrap(7, 6), PositionConstraint.adapterScrap(8, 7) 4908ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar ); 4918ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 4928ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 493b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 4948ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar public void positionStatesTest(int itemCount, int firstLayoutStartIndex, 495e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar int firstLayoutItemCount, AdapterOps adapterChanges, 496e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar final PositionConstraint... constraints) throws Throwable { 497e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar positionStatesTest(itemCount, firstLayoutStartIndex, firstLayoutItemCount, null, 498e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar adapterChanges, constraints); 499e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar } 500e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar public void positionStatesTest(int itemCount, int firstLayoutStartIndex, 501e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar int firstLayoutItemCount,TestAdapter adapter, AdapterOps adapterChanges, 502e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar final PositionConstraint... constraints) throws Throwable { 503e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar setupBasic(itemCount, firstLayoutStartIndex, firstLayoutItemCount, adapter); 504b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar mLayoutManager.expectLayouts(2); 5058ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar mLayoutManager.mOnLayoutCallbacks = new OnLayoutCallbacks() { 5068ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar @Override 5078ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar void beforePreLayout(RecyclerView.Recycler recycler, AnimationLayoutManager lm, 5088ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar RecyclerView.State state) { 5098ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar super.beforePreLayout(recycler, lm, state); 5108ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar //harmless 5118ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar lm.detachAndScrapAttachedViews(recycler); 5128ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar final int[] ids = new int[constraints.length]; 5138ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar for (int i = 0; i < constraints.length; i++) { 5148ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar ids[i] = constraints[i].mPreLayoutPos; 5158ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 5168ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar Map<Integer, CollectPositionResult> positions 517e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar = collectPositions(lm.mRecyclerView, recycler, state, ids); 5188ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar for (PositionConstraint constraint : constraints) { 5198ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar if (constraint.mPreLayoutPos != -1) { 5208ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar constraint.validate(state, positions.get(constraint.mPreLayoutPos), 5218ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar lm.getLog()); 5228ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 5238ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 5248ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 5258ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 5268ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar @Override 5278ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar void beforePostLayout(RecyclerView.Recycler recycler, AnimationLayoutManager lm, 5288ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar RecyclerView.State state) { 5298ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar super.beforePostLayout(recycler, lm, state); 5308ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar lm.detachAndScrapAttachedViews(recycler); 5318ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar final int[] ids = new int[constraints.length]; 5328ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar for (int i = 0; i < constraints.length; i++) { 5338ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar ids[i] = constraints[i].mPostLayoutPos; 5348ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 5358ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar Map<Integer, CollectPositionResult> positions 536e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar = collectPositions(lm.mRecyclerView, recycler, state, ids); 5378ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar for (PositionConstraint constraint : constraints) { 5388ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar if (constraint.mPostLayoutPos >= 0) { 5398ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar constraint.validate(state, positions.get(constraint.mPostLayoutPos), 5408ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar lm.getLog()); 5418ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 5428ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 5438ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 5448ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar }; 5458ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar adapterChanges.run(mTestAdapter); 546b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar mLayoutManager.waitForLayout(2); 547e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar checkForMainThreadException(); 5488ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar for (PositionConstraint constraint : constraints) { 5498ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar constraint.assertValidate(); 5508ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 551b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 552b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 553b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar class AnimationLayoutManager extends TestLayoutManager { 554b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 5558ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar private int mTotalLayoutCount = 0; 5568ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar private String log; 5578ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 558b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar OnLayoutCallbacks mOnLayoutCallbacks = new OnLayoutCallbacks() { 559b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar }; 560b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 5618ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 5628ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 563b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar @Override 564c35968d173f900d8024bdf38174e2225c9a7f311Chet Haase public boolean supportsPredictiveItemAnimations() { 565b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar return true; 566b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 567b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 5688ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar public String getLog() { 5698ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar return log; 5708ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 5718ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 572668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar private String prepareLog(RecyclerView.Recycler recycler, RecyclerView.State state, boolean done) { 5738ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar StringBuilder builder = new StringBuilder(); 574668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar builder.append("is pre layout:").append(state.isPreLayout()).append(", done:").append(done); 575668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar builder.append("\nViewHolders:\n"); 5768ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar for (RecyclerView.ViewHolder vh : ((TestRecyclerView)mRecyclerView).collectViewHolders()) { 5778ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar builder.append(vh).append("\n"); 5788ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 5798ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar builder.append("scrap:\n"); 5808ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar for (RecyclerView.ViewHolder vh : recycler.getScrapList()) { 5818ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar builder.append(vh).append("\n"); 5828ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 583668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar 584668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar if (state.isPreLayout() && !done) { 5858ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar log = "\n" + builder.toString(); 5868ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } else { 5878ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar log += "\n" + builder.toString(); 5888ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 5898ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar return log; 5908ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 5918ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 592b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar @Override 593b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar public void expectLayouts(int count) { 594b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar super.expectLayouts(count); 595b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar mOnLayoutCallbacks.mLayoutCount = 0; 596b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 597b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 598b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar public void setOnLayoutCallbacks(OnLayoutCallbacks onLayoutCallbacks) { 599b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar mOnLayoutCallbacks = onLayoutCallbacks; 600b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 601b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 602b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar @Override 603b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar public final void onLayoutChildren(RecyclerView.Recycler recycler, 604b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar RecyclerView.State state) { 605b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar try { 6068ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar mTotalLayoutCount++; 607668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar prepareLog(recycler, state, false); 608668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar if (state.isPreLayout()) { 609668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar validateOldPositions(recycler, state); 610668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar } else { 611668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar validateClearedOldPositions(recycler, state); 612668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar } 613b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar mOnLayoutCallbacks.onLayoutChildren(recycler, this, state); 614668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar prepareLog(recycler, state, true); 615b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } finally { 616b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar layoutLatch.countDown(); 617d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 618b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 619b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 620668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar private void validateClearedOldPositions(RecyclerView.Recycler recycler, 621668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar RecyclerView.State state) { 622668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar if (getTestRecyclerView() == null) { 623668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar return; 624668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar } 625668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar for (RecyclerView.ViewHolder viewHolder : getTestRecyclerView().collectViewHolders()) { 626668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar assertEquals("there should NOT be an old position in post layout", 627668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar RecyclerView.NO_POSITION, viewHolder.mOldPosition); 628668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar assertEquals("there should NOT be a pre layout position in post layout", 629668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar RecyclerView.NO_POSITION, viewHolder.mPreLayoutPosition); 630668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar } 631668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar } 632668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar 633668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar private void validateOldPositions(RecyclerView.Recycler recycler, 634668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar RecyclerView.State state) { 635668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar if (getTestRecyclerView() == null) { 636668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar return; 637668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar } 638668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar for (RecyclerView.ViewHolder viewHolder : getTestRecyclerView().collectViewHolders()) { 639668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar if (!viewHolder.isRemoved() && !viewHolder.isInvalid()) { 640668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar assertTrue("there should be an old position in pre-layout", 641668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar viewHolder.mOldPosition != RecyclerView.NO_POSITION); 642668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar } 643668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar } 644668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar } 645668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar 6468ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar public int getTotalLayoutCount() { 6478ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar return mTotalLayoutCount; 6488ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 6498ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 650d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar @Override 651d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar public boolean canScrollVertically() { 652d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar return true; 653d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar } 654d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar 655d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar @Override 656d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, 657d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar RecyclerView.State state) { 658d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar mOnLayoutCallbacks.onScroll(dy, recycler, state); 659d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar return super.scrollVerticallyBy(dy, recycler, state); 660d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar } 661b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 662b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar public void onPostDispatchLayout() { 663b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar mOnLayoutCallbacks.postDispatchLayout(); 664b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 665b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 666b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar @Override 667b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar public void waitForLayout(long timeout, TimeUnit timeUnit) throws Throwable { 668b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar super.waitForLayout(timeout, timeUnit); 669b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar checkForMainThreadException(); 670b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 671d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 672d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 673b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar abstract class OnLayoutCallbacks { 674b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 675b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar int mLayoutMin = Integer.MIN_VALUE; 676b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 677b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar int mLayoutItemCount = Integer.MAX_VALUE; 678b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 679b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar int expectedPreLayoutItemCount = -1; 680b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 681b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar int expectedPostLayoutItemCount = -1; 682b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 683b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar int mDeletedViewCount; 684b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 6858ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar int mLayoutCount = 0; 6868ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 687b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar void setExpectedItemCounts(int preLayout, int postLayout) { 688b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar expectedPreLayoutItemCount = preLayout; 689b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar expectedPostLayoutItemCount = postLayout; 690b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 691b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 692b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar void reset() { 693b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar mLayoutMin = Integer.MIN_VALUE; 694b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar mLayoutItemCount = Integer.MAX_VALUE; 695b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar expectedPreLayoutItemCount = -1; 696b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar expectedPostLayoutItemCount = -1; 6978ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar mLayoutCount = 0; 698b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 699b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 700b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar void beforePreLayout(RecyclerView.Recycler recycler, 701b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar AnimationLayoutManager lm, RecyclerView.State state) { 702b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar mDeletedViewCount = 0; 703b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar for (int i = 0; i < lm.getChildCount(); i++) { 704b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar View v = lm.getChildAt(i); 705b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar if (lm.getLp(v).isItemRemoved()) { 706b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar mDeletedViewCount++; 707b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 708b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 709b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 710b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 711b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar void doLayout(RecyclerView.Recycler recycler, AnimationLayoutManager lm, 712b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar RecyclerView.State state) { 713b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar if (DEBUG) { 714b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar Log.d(TAG, "item count " + state.getItemCount()); 715b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 716b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar lm.detachAndScrapAttachedViews(recycler); 717b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar final int start = mLayoutMin == Integer.MIN_VALUE ? 0 : mLayoutMin; 718b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar final int count = mLayoutItemCount 719b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar == Integer.MAX_VALUE ? state.getItemCount() : mLayoutItemCount; 7208ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar int skippedAdd = lm.layoutRange(recycler, start, start + count); 721b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar assertEquals("correct # of children should be laid out", 7228ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar count - skippedAdd, lm.getChildCount()); 7238ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar lm.assertVisibleItemPositions(); 724b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 725b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 726b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar void onLayoutChildren(RecyclerView.Recycler recycler, AnimationLayoutManager lm, 727b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar RecyclerView.State state) { 728b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 7298ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar if (state.isPreLayout()) { 730b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar if (expectedPreLayoutItemCount != -1) { 731b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar assertEquals("on pre layout, state should return abstracted adapter size", 732b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar expectedPreLayoutItemCount, state.getItemCount()); 733b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 734b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar beforePreLayout(recycler, lm, state); 7358ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } else { 736b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar if (expectedPostLayoutItemCount != -1) { 737b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar assertEquals("on post layout, state should return real adapter size", 738b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar expectedPostLayoutItemCount, state.getItemCount()); 739b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 740b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar beforePostLayout(recycler, lm, state); 741b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 742b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar doLayout(recycler, lm, state); 7438ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar if (state.isPreLayout()) { 744b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar afterPreLayout(recycler, lm, state); 7458ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } else { 746b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar afterPostLayout(recycler, lm, state); 747b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 748b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar mLayoutCount++; 749b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 750b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 751b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar void afterPreLayout(RecyclerView.Recycler recycler, AnimationLayoutManager layoutManager, 752b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar RecyclerView.State state) { 753b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 754b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 755b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar void beforePostLayout(RecyclerView.Recycler recycler, AnimationLayoutManager layoutManager, 756b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar RecyclerView.State state) { 757b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 758b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 759b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar void afterPostLayout(RecyclerView.Recycler recycler, AnimationLayoutManager layoutManager, 760b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar RecyclerView.State state) { 761b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 762b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 763b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar void postDispatchLayout() { 764b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 765b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 766d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar public void onScroll(int dx, RecyclerView.Recycler recycler, RecyclerView.State state) { 767d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar 768d3f1c99a290de13631f9635e06444f75344967d2Yigit Boyar } 769b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 770b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 771b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar class TestRecyclerView extends RecyclerView { 77211b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar 773888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar CountDownLatch drawLatch; 774b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 775b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar public TestRecyclerView(Context context) { 776b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar super(context); 777b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 778b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 779b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar public TestRecyclerView(Context context, AttributeSet attrs) { 780b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar super(context, attrs); 781b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 782b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 783b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar public TestRecyclerView(Context context, AttributeSet attrs, int defStyle) { 784b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar super(context, attrs, defStyle); 785b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 786b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 7878ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar @Override 7888ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar void initAdapterManager() { 7898ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar super.initAdapterManager(); 7908ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar mAdapterHelper.mOnItemProcessedCallback = new Runnable() { 7918ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar @Override 7928ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar public void run() { 7938ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar validatePostUpdateOp(); 7948ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 7958ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar }; 7968ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 7978ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 798888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar public void expectDraw(int count) { 799888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar drawLatch = new CountDownLatch(count); 800888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar } 801888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar 802888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar public void waitForDraw(long timeout) throws Throwable { 803888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar drawLatch.await(timeout * (DEBUG ? 100 : 1), TimeUnit.SECONDS); 804888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar assertEquals("all expected draws should happen at the expected time frame", 805888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar 0, drawLatch.getCount()); 806888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar } 807888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar 8088ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar List<ViewHolder> collectViewHolders() { 8098ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar List<ViewHolder> holders = new ArrayList<ViewHolder>(); 8108ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar final int childCount = getChildCount(); 8118ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar for (int i = 0; i < childCount; i++) { 8128ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar ViewHolder holder = getChildViewHolderInt(getChildAt(i)); 8138ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar if (holder != null) { 8148ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar holders.add(holder); 8158ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 8168ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 8178ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar return holders; 8188ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 8198ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 8208ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 8218ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar private void validateViewHolderPositions() { 8228ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar final Set<Integer> existingOffsets = new HashSet<Integer>(); 823668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar int childCount = getChildCount(); 824668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar StringBuilder log = new StringBuilder(); 8258ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar for (int i = 0; i < childCount; i++) { 8268ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar ViewHolder vh = getChildViewHolderInt(getChildAt(i)); 827668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar TestViewHolder tvh = (TestViewHolder) vh; 828668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar log.append(tvh.mBindedItem).append(vh) 829668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar .append(" hidden:") 830668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar .append(mChildHelper.mHiddenViews.contains(vh.itemView)) 831668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar .append("\n"); 832668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar } 833668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar for (int i = 0; i < childCount; i++) { 834668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar ViewHolder vh = getChildViewHolderInt(getChildAt(i)); 835668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar if (vh.isInvalid()) { 836668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar continue; 837668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar } 838668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar if (vh.getPosition() < 0) { 839668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar LayoutManager lm = getLayoutManager(); 840668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar for (int j = 0; j < lm.getChildCount(); j ++) { 841668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar assertNotSame("removed view holder should not be in LM's child list", 842668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar vh.itemView, lm.getChildAt(j)); 8438ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 844668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar } else if (!mChildHelper.mHiddenViews.contains(vh.itemView)) { 8458ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar if (!existingOffsets.add(vh.getPosition())) { 846668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar throw new IllegalStateException("view holder position conflict for " 847668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar + "existing views " + vh + "\n" + log); 8488ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 8498ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 8508ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 8518ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 8528ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 8538ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar void validatePostUpdateOp() { 8548ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar try { 8558ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar validateViewHolderPositions(); 8568ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar if (super.mState.isPreLayout()) { 8578ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar validatePreLayoutSequence((AnimationLayoutManager) getLayoutManager()); 8588ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 8598ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar validateAdapterPosition((AnimationLayoutManager) getLayoutManager()); 8608ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } catch (Throwable t) { 8618ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar postExceptionToInstrumentation(t); 8628ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 8638ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 8648ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 8658ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 8668ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 8678ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar private void validateAdapterPosition(AnimationLayoutManager lm) { 8688ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar for (ViewHolder vh : collectViewHolders()) { 8698ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar if (!vh.isRemoved() && vh.mPreLayoutPosition >= 0) { 8708ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar assertEquals("adapter position calculations should match view holder " 871668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar + "pre layout:" + mState.isPreLayout() 872668e774379c036a5d53d07ec69ed9ebee13a1fd9Yigit Boyar + " positions\n" + vh + "\n" + lm.getLog(), 8738ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar mAdapterHelper.findPositionOffset(vh.mPreLayoutPosition), vh.mPosition); 8748ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 8758ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 8768ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 8778ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 8788ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar // ensures pre layout positions are continuous block. This is not necessarily a case 8798ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar // but valid in test RV 8808ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar private void validatePreLayoutSequence(AnimationLayoutManager lm) { 8818ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar Set<Integer> preLayoutPositions = new HashSet<Integer>(); 8828ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar for (ViewHolder vh : collectViewHolders()) { 8838ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar assertTrue("pre layout positions should be distinct " + lm.getLog(), 8848ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar preLayoutPositions.add(vh.mPreLayoutPosition)); 8858ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 8868ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar int minPos = Integer.MAX_VALUE; 8878ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar for (Integer pos : preLayoutPositions) { 8888ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar if (pos < minPos) { 8898ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar minPos = pos; 8908ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 8918ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 8928ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar for (int i = 1; i < preLayoutPositions.size(); i++) { 8938ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar assertNotNull("next position should exist " + lm.getLog(), 8948ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar preLayoutPositions.contains(minPos + i)); 8958ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 8968ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 8978ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 898888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar @Override 899888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar protected void dispatchDraw(Canvas canvas) { 900888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar super.dispatchDraw(canvas); 901888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar if (drawLatch != null) { 902888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar drawLatch.countDown(); 903888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar } 904888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar } 905888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar 906b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar @Override 907b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar void dispatchLayout() { 908b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar try { 909b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar super.dispatchLayout(); 910b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar if (getLayoutManager() instanceof AnimationLayoutManager) { 911b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar ((AnimationLayoutManager) getLayoutManager()).onPostDispatchLayout(); 912b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 913b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } catch (Throwable t) { 914b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar postExceptionToInstrumentation(t); 915b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 916b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 917b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 918b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 9198ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 9208ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 9218ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 9228ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar abstract class AdapterOps { 9238ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 9248ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar final public void run(TestAdapter adapter) throws Throwable { 9258ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar onRun(adapter); 9268ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 9278ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 9288ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar abstract void onRun(TestAdapter testAdapter) throws Throwable; 9298ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 9308ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 9318ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar static class CollectPositionResult { 9328ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 9338ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar // true if found in scrap 9348ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar public RecyclerView.ViewHolder scrapResult; 9358ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 9368ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar public RecyclerView.ViewHolder adapterResult; 9378ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 9388ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar static CollectPositionResult fromScrap(RecyclerView.ViewHolder viewHolder) { 9398ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar CollectPositionResult cpr = new CollectPositionResult(); 9408ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar cpr.scrapResult = viewHolder; 9418ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar return cpr; 9428ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 9438ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 9448ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar static CollectPositionResult fromAdapter(RecyclerView.ViewHolder viewHolder) { 9458ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar CollectPositionResult cpr = new CollectPositionResult(); 9468ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar cpr.adapterResult = viewHolder; 9478ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar return cpr; 9488ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 9498ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 9508ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 9518ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar static class PositionConstraint { 9528ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 9538ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar public static enum Type { 9548ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar scrap, 9558ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar adapter, 9568ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar adapterScrap /*first pass adapter, second pass scrap*/ 9578ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 9588ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 9598ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar Type mType; 9608ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 9618ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar int mOldPos; // if VH 9628ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 9638ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar int mPreLayoutPos; 9648ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 9658ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar int mPostLayoutPos; 9668ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 9678ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar int mValidateCount = 0; 9688ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 9698ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar public static PositionConstraint scrap(int oldPos, int preLayoutPos, int postLayoutPos) { 9708ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar PositionConstraint constraint = new PositionConstraint(); 9718ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar constraint.mType = Type.scrap; 9728ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar constraint.mOldPos = oldPos; 9738ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar constraint.mPreLayoutPos = preLayoutPos; 9748ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar constraint.mPostLayoutPos = postLayoutPos; 9758ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar return constraint; 9768ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 9778ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 9788ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar public static PositionConstraint adapterScrap(int preLayoutPos, int position) { 9798ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar PositionConstraint constraint = new PositionConstraint(); 9808ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar constraint.mType = Type.adapterScrap; 9818ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar constraint.mOldPos = RecyclerView.NO_POSITION; 9828ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar constraint.mPreLayoutPos = preLayoutPos; 9838ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar constraint.mPostLayoutPos = position;// adapter pos does not change 9848ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar return constraint; 9858ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 9868ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 9878ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar public static PositionConstraint adapter(int position) { 9888ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar PositionConstraint constraint = new PositionConstraint(); 9898ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar constraint.mType = Type.adapter; 9908ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar constraint.mPreLayoutPos = RecyclerView.NO_POSITION; 9918ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar constraint.mOldPos = RecyclerView.NO_POSITION; 9928ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar constraint.mPostLayoutPos = position;// adapter pos does not change 9938ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar return constraint; 9948ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 9958ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 9968ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar public void assertValidate() { 9978ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar int expectedValidate = 0; 9988ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar if (mPreLayoutPos >= 0) { 9998ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar expectedValidate ++; 10008ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 10018ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar if (mPostLayoutPos >= 0) { 10028ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar expectedValidate ++; 10038ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 10048ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar assertEquals("should run all validates", expectedValidate, mValidateCount); 10058ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 10068ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 10078ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar @Override 10088ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar public String toString() { 10098ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar return "Cons{" + 10108ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar "t=" + mType.name() + 10118ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar ", old=" + mOldPos + 10128ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar ", pre=" + mPreLayoutPos + 10138ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar ", post=" + mPostLayoutPos + 10148ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar '}'; 10158ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 10168ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 10178ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar public void validate(RecyclerView.State state, CollectPositionResult result, String log) { 10188ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar mValidateCount ++; 10198ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar assertNotNull(this + ": result should not be null\n" + log, result); 10208ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar RecyclerView.ViewHolder viewHolder; 10218ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar if (mType == Type.scrap || (mType == Type.adapterScrap && !state.isPreLayout())) { 10228ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar assertNotNull(this + ": result should come from scrap\n" + log, result.scrapResult); 10238ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar viewHolder = result.scrapResult; 10248ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } else { 10258ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar assertNotNull(this + ": result should come from adapter\n" + log, 10268ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar result.adapterResult); 10278ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar assertEquals(this + ": old position should be none when it came from adapter\n" + log, 10288ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar RecyclerView.NO_POSITION, result.adapterResult.getOldPosition()); 10298ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar viewHolder = result.adapterResult; 10308ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 10318ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar if (state.isPreLayout()) { 10328ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar assertEquals(this + ": pre-layout position should match\n" + log, mPreLayoutPos, 1033e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar viewHolder.mPreLayoutPosition == -1 ? viewHolder.mPosition : 10348ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar viewHolder.mPreLayoutPosition); 10358ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar assertEquals(this + ": pre-layout getPosition should match\n" + log, mPreLayoutPos, 10368ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar viewHolder.getPosition()); 10378ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar if (mType == Type.scrap) { 10388ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar assertEquals(this + ": old position should match\n" + log, mOldPos, 10398ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar result.scrapResult.getOldPosition()); 1040b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 10418ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } else if (mType == Type.adapter || mType == Type.adapterScrap || !result.scrapResult 10428ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar .isRemoved()) { 1043e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar assertEquals(this + ": post-layout position should match\n" + log + "\n\n" 1044e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar + viewHolder, mPostLayoutPos, viewHolder.getPosition()); 1045b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 1046b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 1047b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 1048d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase} 1049