GridLayoutManagerCacheTest.java revision 42e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790
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;
26754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikasimport android.support.test.filters.MediumTest;
27ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craikimport android.support.test.filters.SdkSuppress;
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
8542e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityRule.runOnUiThread(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);
9942e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas            mActivityRule.runOnUiThread(new Runnable() {
100ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik                @Override
101ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik                public void run() {
102ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik                    mRecyclerView.mRecycler.recycleAndClearCachedViews();
10307b2e072ee7e8f424eb95abc77695dc2c5a786bbChris Craik                    mRecyclerView.mGapWorker.postFromTraversal(mRecyclerView, mDx, mDy);
104ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik
105ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik                    // Lie about post time, so prefetch executes even if it is delayed
10607b2e072ee7e8f424eb95abc77695dc2c5a786bbChris Craik                    mRecyclerView.mGapWorker.mPostTimeNs += TimeUnit.SECONDS.toNanos(5);
107ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik                }
108ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik            });
109ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik            mGlm.waitForPrefetch(1);
110ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik        }
111ec4b5429886bfe93707a85823cf40de107bd9dc6Chris Craik
11242e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityRule.runOnUiThread(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