1/* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.support.v7.widget; 18 19import static org.hamcrest.CoreMatchers.is; 20import static org.hamcrest.MatcherAssert.assertThat; 21 22import android.os.Build; 23import android.support.test.filters.SdkSuppress; 24import android.support.test.filters.SmallTest; 25import android.support.test.runner.AndroidJUnit4; 26 27import org.junit.Test; 28import org.junit.runner.RunWith; 29 30import java.util.ArrayList; 31import java.util.concurrent.CountDownLatch; 32import java.util.concurrent.TimeUnit; 33 34@SmallTest 35@SdkSuppress(minSdkVersion = Build.VERSION_CODES.LOLLIPOP) 36@RunWith(AndroidJUnit4.class) 37public class RecyclerViewPrefetchTest extends BaseRecyclerViewInstrumentationTest { 38 private class PrefetchLayoutManager extends TestLayoutManager { 39 CountDownLatch prefetchLatch = new CountDownLatch(1); 40 41 @Override 42 public boolean canScrollVertically() { 43 return true; 44 } 45 46 @Override 47 public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) { 48 super.onLayoutChildren(recycler, state); 49 detachAndScrapAttachedViews(recycler); 50 layoutRange(recycler, 0, 5); 51 } 52 53 @Override 54 public void onLayoutCompleted(RecyclerView.State state) { 55 super.onLayoutCompleted(state); 56 layoutLatch.countDown(); 57 } 58 59 @Override 60 public void collectAdjacentPrefetchPositions(int dx, int dy, RecyclerView.State state, 61 LayoutPrefetchRegistry layoutPrefetchRegistry) { 62 prefetchLatch.countDown(); 63 layoutPrefetchRegistry.addPosition(6, 0); 64 } 65 66 void waitForPrefetch(int time) throws InterruptedException { 67 assertThat(prefetchLatch.await(time, TimeUnit.SECONDS), 68 is(true)); 69 getInstrumentation().runOnMainSync(new Runnable() { 70 @Override 71 public void run() { 72 } 73 }); 74 } 75 } 76 77 private ArrayList<RecyclerView.ViewHolder> cachedViews() { 78 return mRecyclerView.mRecycler.mCachedViews; 79 } 80 81 @Test 82 public void prefetchTest() throws Throwable { 83 RecyclerView recyclerView = new RecyclerView(getActivity()); 84 recyclerView.setAdapter(new TestAdapter(50)); 85 PrefetchLayoutManager layout = new PrefetchLayoutManager(); 86 recyclerView.setLayoutManager(layout); 87 88 { 89 layout.expectLayouts(1); 90 setRecyclerView(recyclerView); 91 layout.waitForLayout(10); 92 } 93 94 assertThat(layout.prefetchLatch.getCount(), is(1L)); // shouldn't have fired yet 95 assertThat(cachedViews().size(), is(0)); 96 smoothScrollBy(50); 97 98 layout.waitForPrefetch(10); 99 assertThat(cachedViews().size(), is(1)); 100 assertThat(cachedViews().get(0).getAdapterPosition(), is(6)); 101 } 102}