GridLayoutManagerCacheTest.java revision e9f9cd8d0e9008340985d17a2541ab24b3adb391
1ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik/* 2ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik * Copyright (C) 2016 The Android Open Source Project 3ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik * 4ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik * Licensed under the Apache License, Version 2.0 (the "License"); 5ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik * you may not use this file except in compliance with the License. 6ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik * You may obtain a copy of the License at 7ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik * 8ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik * http://www.apache.org/licenses/LICENSE-2.0 9ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik * 10ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik * Unless required by applicable law or agreed to in writing, software 11ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik * distributed under the License is distributed on an "AS IS" BASIS, 12ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik * See the License for the specific language governing permissions and 14ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik * limitations under the License. 15ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik */ 16ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik 17ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craikpackage android.support.v7.widget; 18ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik 19e9f9cd8d0e9008340985d17a2541ab24b3adb391Aurimas Liutikasimport static android.support.v7.widget.LinearLayoutManager.HORIZONTAL; 20e9f9cd8d0e9008340985d17a2541ab24b3adb391Aurimas Liutikasimport static android.support.v7.widget.LinearLayoutManager.VERTICAL; 21e9f9cd8d0e9008340985d17a2541ab24b3adb391Aurimas Liutikas 22e9f9cd8d0e9008340985d17a2541ab24b3adb391Aurimas Liutikasimport static org.junit.Assert.assertEquals; 23e9f9cd8d0e9008340985d17a2541ab24b3adb391Aurimas Liutikasimport static org.junit.Assert.assertTrue; 24e9f9cd8d0e9008340985d17a2541ab24b3adb391Aurimas Liutikas 25ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craikimport android.os.Build; 26ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craikimport android.support.test.filters.SdkSuppress; 27ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craikimport android.test.suitebuilder.annotation.MediumTest; 28ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik 29ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craikimport org.junit.Test; 30ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craikimport org.junit.runner.RunWith; 31ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craikimport org.junit.runners.Parameterized; 32ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik 33ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craikimport java.util.ArrayList; 34ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craikimport java.util.List; 35ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craikimport java.util.concurrent.TimeUnit; 36ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik 37ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik@RunWith(Parameterized.class) 38ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik@SdkSuppress(minSdkVersion = Build.VERSION_CODES.LOLLIPOP) 39ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craikpublic class GridLayoutManagerCacheTest extends BaseGridLayoutManagerTest { 40ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik 41ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik final Config mConfig; 42ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik final int mDx; 43ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik final int mDy; 44ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik 45ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik public GridLayoutManagerCacheTest(Config config, int dx, int dy) { 46ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik mConfig = config; 47ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik mDx = dx; 48ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik mDy = dy; 49ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik } 50ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik 51e9f9cd8d0e9008340985d17a2541ab24b3adb391Aurimas Liutikas @Parameterized.Parameters(name = "config:{0},dx:{1},dy:{2}") 52ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik public static List<Object[]> getParams() { 53ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik List<Object[]> result = new ArrayList<>(); 54ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik List<Config> configs = createBaseVariations(); 55ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik for (Config config : configs) { 56ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik for (int dx : new int[] {-1, 0, 1}) { 57ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik for (int dy : new int[] {-1, 0, 1}) { 58ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik result.add(new Object[]{config, dx, dy}); 59ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik } 60ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik } 61ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik } 62ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik return result; 63ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik } 64ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik 65ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik private ArrayList<RecyclerView.ViewHolder> cachedViews() { 66ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik return mRecyclerView.mRecycler.mCachedViews; 67ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik } 68ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik 69ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik private boolean cachedViewsContains(int position) { 70ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik // Note: can't make assumptions about order here, so just check all cached views 71ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik for (int i = 0; i < cachedViews().size(); i++) { 72ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik if (cachedViews().get(i).getAdapterPosition() == position) return true; 73ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik } 74ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik return false; 75ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik } 76ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik 77ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik @MediumTest 78ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik @Test 79ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik public void cacheAndPrefetch() throws Throwable { 80ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik final Config config = (Config) mConfig.clone(); 81ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik RecyclerView recyclerView = setupBasic(config); 82ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik waitForFirstLayout(recyclerView); 83ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik 84ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik 85ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik runTestOnUiThread(new Runnable() { 86ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik @Override 87ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik public void run() { 88ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik // pretend to have an extra 5s before next frame so prefetch won't abort early 89ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik ((WrappedRecyclerView)mRecyclerView).setDrawingTimeOffset(5000); 90ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik 91ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik // scroll to the middle, so we can move in either direction 92ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik mRecyclerView.scrollToPosition(mConfig.mItemCount / 2); 93ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik } 94ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik }); 95ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik 96ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik mRecyclerView.setItemViewCacheSize(0); 97ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik { 98ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik mGlm.expectPrefetch(1); 99ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik runTestOnUiThread(new Runnable() { 100ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik @Override 101ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik public void run() { 102ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik mRecyclerView.mRecycler.recycleAndClearCachedViews(); 103ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik mRecyclerView.mViewPrefetcher.postFromTraversal(mDx, mDy); 104ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik 105ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik // Lie about post time, so prefetch executes even if it is delayed 106ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik mRecyclerView.mViewPrefetcher.mPostTimeNanos += TimeUnit.SECONDS.toNanos(5); 107ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik } 108ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik }); 109ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik mGlm.waitForPrefetch(1); 110ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik } 111ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik 112ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik runTestOnUiThread(new Runnable() { 113ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik @Override 114ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik public void run() { 115ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik // validate cache state on UI thread 116ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik if ((config.mOrientation == HORIZONTAL && mDx == 0) 117ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik || (config.mOrientation == VERTICAL && mDy == 0)) { 118ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik assertEquals(0, cachedViews().size()); 119ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik } else { 120ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik assertEquals(config.mSpanCount, cachedViews().size()); 121ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik 122ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik boolean reverseScroll = config.mOrientation == HORIZONTAL ? mDx < 0 : mDy < 0; 123ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik int lastVisibleItemPosition = mGlm.findLastVisibleItemPosition(); 124ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik int firstVisibleItemPosition = mGlm.findFirstVisibleItemPosition(); 125ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik 126ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik for (int i = 0; i < config.mSpanCount; i++) { 127ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik if (mConfig.mReverseLayout == reverseScroll) { 128ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik // Pos scroll on pos layout, or reverse scroll on reverse layout 129ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik // = toward last 130ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik assertTrue(cachedViewsContains(lastVisibleItemPosition + 1 + i)); 131ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik } else { 132ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik // Pos scroll on reverse layout, or reverse scroll on pos layout 133ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik // = toward first 134ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik assertTrue(cachedViewsContains(firstVisibleItemPosition - 1 - i)); 135ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik } 136ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik } 137ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik } 138ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik } 139ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik }); 140ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik } 141ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik} 142