10a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar/* 20a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar * Copyright (C) 2015 The Android Open Source Project 30a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar * 40a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar * Licensed under the Apache License, Version 2.0 (the "License"); 50a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar * you may not use this file except in compliance with the License. 60a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar * You may obtain a copy of the License at 70a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar * 80a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar * http://www.apache.org/licenses/LICENSE-2.0 90a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar * 100a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar * Unless required by applicable law or agreed to in writing, software 110a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar * distributed under the License is distributed on an "AS IS" BASIS, 120a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar * See the License for the specific language governing permissions and 140a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar * limitations under the License. 150a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar */ 160a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar 170a017072206f93474ccd2706e7983c2ff778b904Yigit Boyarpackage android.support.v7.widget; 180a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar 19e9f9cd8d0e9008340985d17a2541ab24b3adb391Aurimas Liutikasimport static org.junit.Assert.assertEquals; 200a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar 210a017072206f93474ccd2706e7983c2ff778b904Yigit Boyarimport android.graphics.Rect; 220a017072206f93474ccd2706e7983c2ff778b904Yigit Boyarimport android.os.Parcel; 230a017072206f93474ccd2706e7983c2ff778b904Yigit Boyarimport android.os.Parcelable; 24754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikasimport android.support.test.filters.LargeTest; 250a017072206f93474ccd2706e7983c2ff778b904Yigit Boyarimport android.util.Log; 260a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar 27e9f9cd8d0e9008340985d17a2541ab24b3adb391Aurimas Liutikasimport org.junit.Test; 28e9f9cd8d0e9008340985d17a2541ab24b3adb391Aurimas Liutikasimport org.junit.runner.RunWith; 29e9f9cd8d0e9008340985d17a2541ab24b3adb391Aurimas Liutikasimport org.junit.runners.Parameterized; 30e9f9cd8d0e9008340985d17a2541ab24b3adb391Aurimas Liutikas 310a017072206f93474ccd2706e7983c2ff778b904Yigit Boyarimport java.util.ArrayList; 320a017072206f93474ccd2706e7983c2ff778b904Yigit Boyarimport java.util.List; 330a017072206f93474ccd2706e7983c2ff778b904Yigit Boyarimport java.util.Map; 340a017072206f93474ccd2706e7983c2ff778b904Yigit Boyarimport java.util.UUID; 350a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar 360a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar@RunWith(Parameterized.class) 37dca8e68e966915b8314095e71538d231a7eee575Yigit Boyar@LargeTest 380a017072206f93474ccd2706e7983c2ff778b904Yigit Boyarpublic class StaggeredGridLayoutManagerSavedStateTest extends BaseStaggeredGridLayoutManagerTest { 390a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar private final Config mConfig; 400a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar private final boolean mWaitForLayout; 410a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar private final boolean mLoadDataAfterRestore; 420a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar private final PostLayoutRunnable mPostLayoutOperations; 430a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar 440a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public StaggeredGridLayoutManagerSavedStateTest( 450a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar Config config, boolean waitForLayout, boolean loadDataAfterRestore, 460a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar PostLayoutRunnable postLayoutOperations) throws CloneNotSupportedException { 470a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar this.mConfig = (Config) config.clone(); 480a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar this.mWaitForLayout = waitForLayout; 490a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar this.mLoadDataAfterRestore = loadDataAfterRestore; 500a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar this.mPostLayoutOperations = postLayoutOperations; 510a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar if (postLayoutOperations != null) { 520a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar postLayoutOperations.mTest = this; 530a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar } 540a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar } 550a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar 56e9f9cd8d0e9008340985d17a2541ab24b3adb391Aurimas Liutikas @Parameterized.Parameters(name = "config={0},waitForLayout={1},loadDataAfterRestore={2}" 57e9f9cd8d0e9008340985d17a2541ab24b3adb391Aurimas Liutikas + ",postLayoutRunnable={3}") 580a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public static List<Object[]> getParams() throws CloneNotSupportedException { 590a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar List<Config> variations = createBaseVariations(); 600a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar 610a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar PostLayoutRunnable[] postLayoutOptions = new PostLayoutRunnable[]{ 620a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar new PostLayoutRunnable() { 630a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Override 640a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public void run() throws Throwable { 650a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar // do nothing 660a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar } 670a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar 680a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Override 690a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public String describe() { 70142ca4048bd0de39ddbc0e8981914bdff103ead3Aurimas Liutikas return "doing_nothing"; 710a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar } 720a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar }, 730a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar new PostLayoutRunnable() { 740a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Override 750a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public void run() throws Throwable { 760a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar layoutManager().expectLayouts(1); 770a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar scrollToPosition(adapter().getItemCount() * 3 / 4); 780a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar layoutManager().waitForLayout(2); 790a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar } 800a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar 810a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Override 820a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public String describe() { 83142ca4048bd0de39ddbc0e8981914bdff103ead3Aurimas Liutikas return "scroll_to_position_item_count*3/4"; 840a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar } 850a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar }, 860a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar new PostLayoutRunnable() { 870a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Override 880a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public void run() throws Throwable { 890a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar layoutManager().expectLayouts(1); 900a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar scrollToPositionWithOffset(adapter().getItemCount() / 3, 910a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar 50); 920a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar layoutManager().waitForLayout(2); 930a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar } 940a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar 950a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Override 960a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public String describe() { 97142ca4048bd0de39ddbc0e8981914bdff103ead3Aurimas Liutikas return "scroll_to_position_item_count/3_with_positive_offset"; 980a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar } 990a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar }, 1000a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar new PostLayoutRunnable() { 1010a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Override 1020a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public void run() throws Throwable { 1030a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar layoutManager().expectLayouts(1); 1040a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar scrollToPositionWithOffset(adapter().getItemCount() * 2 / 3, 1050a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar -50); 1060a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar layoutManager().waitForLayout(2); 1070a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar } 1080a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar 1090a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Override 1100a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public String describe() { 111142ca4048bd0de39ddbc0e8981914bdff103ead3Aurimas Liutikas return "scroll_to_position_with_negative_offset"; 1120a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar } 1130a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar } 1140a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar }; 1150a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar boolean[] waitForLayoutOptions = new boolean[]{false, true}; 1160a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar boolean[] loadDataAfterRestoreOptions = new boolean[]{false, true}; 1170a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar List<Config> testVariations = new ArrayList<Config>(); 1180a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar testVariations.addAll(variations); 1190a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar for (Config config : variations) { 1200a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar if (config.mSpanCount < 2) { 1210a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar continue; 1220a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar } 1230a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar final Config clone = (Config) config.clone(); 1240a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar clone.mItemCount = clone.mSpanCount - 1; 1250a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar testVariations.add(clone); 1260a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar } 1270a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar 1280a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar List<Object[]> params = new ArrayList<>(); 1290a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar for (Config config : testVariations) { 1300a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar for (PostLayoutRunnable runnable : postLayoutOptions) { 1310a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar for (boolean waitForLayout : waitForLayoutOptions) { 1320a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar for (boolean loadDataAfterRestore : loadDataAfterRestoreOptions) { 1330a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar params.add(new Object[]{config, waitForLayout, loadDataAfterRestore, 1340a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar runnable}); 1350a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar } 1360a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar } 1370a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar } 1380a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar } 1390a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar return params; 1400a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar } 1410a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar 1420a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Test 1430a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public void savedState() throws Throwable { 1440a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar if (DEBUG) { 1450a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar Log.d(TAG, "testing saved state with wait for layout = " + mWaitForLayout + " config " 1460a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar + mConfig + " post layout action " + mPostLayoutOperations.describe()); 1470a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar } 1480a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar setupByConfig(mConfig); 1490a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar if (mLoadDataAfterRestore) { 1500a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar // We are going to re-create items, force non-random item size. 1510a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar mAdapter.mOnBindCallback = new OnBindCallback() { 1520a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Override 1530a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar void onBoundItem(TestViewHolder vh, int position) { 1540a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar } 1550a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar 156e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas @Override 1570a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar boolean assignRandomSize() { 1580a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar return false; 1590a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar } 1600a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar }; 1610a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar } 1620a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar waitFirstLayout(); 1630a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar if (mWaitForLayout) { 1640a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar mPostLayoutOperations.run(); 1650a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar } 1660a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar getInstrumentation().waitForIdleSync(); 1670a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar final int firstCompletelyVisiblePosition = mLayoutManager.findFirstVisibleItemPositionInt(); 1680a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar Map<Item, Rect> before = mLayoutManager.collectChildCoordinates(); 1690a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar Parcelable savedState = mRecyclerView.onSaveInstanceState(); 1700a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar // we append a suffix to the parcelable to test out of bounds 1710a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar String parcelSuffix = UUID.randomUUID().toString(); 1720a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar Parcel parcel = Parcel.obtain(); 1730a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar savedState.writeToParcel(parcel, 0); 1740a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar parcel.writeString(parcelSuffix); 1750a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar removeRecyclerView(); 1760a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar // reset for reading 1770a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar parcel.setDataPosition(0); 1780a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar // re-create 1790a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar savedState = RecyclerView.SavedState.CREATOR.createFromParcel(parcel); 1800a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar removeRecyclerView(); 1810a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar 1820a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar final int itemCount = mAdapter.getItemCount(); 183959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar List<Item> mItems = new ArrayList<>(); 1840a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar if (mLoadDataAfterRestore) { 185959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar mItems.addAll(mAdapter.mItems); 1860a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar mAdapter.deleteAndNotify(0, itemCount); 1870a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar } 1880a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar 1890a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar RecyclerView restored = new RecyclerView(getActivity()); 1900a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar mLayoutManager = new WrappedLayoutManager(mConfig.mSpanCount, mConfig.mOrientation); 1910a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar mLayoutManager.setGapStrategy(mConfig.mGapStrategy); 1920a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar restored.setLayoutManager(mLayoutManager); 1930a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar // use the same adapter for Rect matching 1940a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar restored.setAdapter(mAdapter); 1950a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar restored.onRestoreInstanceState(savedState); 1960a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar 1970a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar if (mLoadDataAfterRestore) { 198959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar mAdapter.resetItemsTo(mItems); 1990a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar } 2000a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar 2010a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar assertEquals("Parcel reading should not go out of bounds", parcelSuffix, 2020a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar parcel.readString()); 2030a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar mLayoutManager.expectLayouts(1); 2040a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar setRecyclerView(restored); 2050a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar mLayoutManager.waitForLayout(2); 2060a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar assertEquals(mConfig + " on saved state, reverse layout should be preserved", 2070a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar mConfig.mReverseLayout, mLayoutManager.getReverseLayout()); 2080a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar assertEquals(mConfig + " on saved state, orientation should be preserved", 2090a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar mConfig.mOrientation, mLayoutManager.getOrientation()); 2100a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar assertEquals(mConfig + " on saved state, span count should be preserved", 2110a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar mConfig.mSpanCount, mLayoutManager.getSpanCount()); 2120a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar assertEquals(mConfig + " on saved state, gap strategy should be preserved", 2130a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar mConfig.mGapStrategy, mLayoutManager.getGapStrategy()); 2140a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar assertEquals(mConfig + " on saved state, first completely visible child position should" 2150a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar + " be preserved", firstCompletelyVisiblePosition, 2160a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar mLayoutManager.findFirstVisibleItemPositionInt()); 2170a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar if (mWaitForLayout) { 2180a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar final boolean strictItemEquality = !mLoadDataAfterRestore; 2190a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar assertRectSetsEqual(mConfig + "\npost layout op:" + mPostLayoutOperations.describe() 2200a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar + ": on restore, previous view positions should be preserved", 2210a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar before, mLayoutManager.collectChildCoordinates(), strictItemEquality); 2220a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar } 2230a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar // TODO add tests for changing values after restore before layout 2240a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar } 2250a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar 2260a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar static abstract class PostLayoutRunnable { 2270a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar StaggeredGridLayoutManagerSavedStateTest mTest; 2280a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public void setup(StaggeredGridLayoutManagerSavedStateTest test) { 2290a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar mTest = test; 2300a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar } 2310a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar 2320a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public GridTestAdapter adapter() { 2330a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar return mTest.mAdapter; 2340a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar } 2350a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar 2360a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public WrappedLayoutManager layoutManager() { 2370a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar return mTest.mLayoutManager; 2380a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar } 2390a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar 2400a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public void scrollToPositionWithOffset(int position, int offset) throws Throwable { 2410a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar mTest.scrollToPositionWithOffset(position, offset); 2420a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar } 2430a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar 2440a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public void scrollToPosition(int position) throws Throwable { 2450a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar mTest.scrollToPosition(position); 2460a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar } 2470a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar 2480a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar abstract void run() throws Throwable; 2490a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar 2500a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar abstract String describe(); 2510a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar 2520a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Override 2530a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public String toString() { 2540a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar return describe(); 2550a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar } 2560a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar } 2570a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar} 258