BaseRecyclerViewInstrumentationTest.java revision 15a9db9177a871c7b1cd65b8923beac1b9b75174
1/* 2 * Copyright (C) 2014 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 android.test.ActivityInstrumentationTestCase2; 20import android.util.Log; 21import android.view.View; 22import android.view.ViewGroup; 23import android.widget.TextView; 24 25import java.util.ArrayList; 26import java.util.List; 27import java.util.concurrent.CountDownLatch; 28import java.util.concurrent.TimeUnit; 29 30abstract public class BaseRecyclerViewInstrumentationTest extends 31 ActivityInstrumentationTestCase2<TestActivity> { 32 33 private static final String TAG = "RecyclerViewTest"; 34 35 private static final boolean DEBUG = true; 36 37 public BaseRecyclerViewInstrumentationTest() { 38 super("android.support.v7.widget", TestActivity.class); 39 } 40 41 class TestViewHolder extends RecyclerView.ViewHolder { 42 43 Item mBindedItem; 44 45 public TestViewHolder(View itemView) { 46 super(itemView); 47 } 48 } 49 50 class TestLayoutManager extends RecyclerView.LayoutManager { 51 52 CountDownLatch layoutLatch; 53 54 public void expectLayouts(int count) { 55 layoutLatch = new CountDownLatch(count); 56 } 57 58 public void waitForLayout(long timeout, TimeUnit timeUnit) throws InterruptedException { 59 layoutLatch.await(timeout, timeUnit); 60 assertEquals("all expected layouts should be executed at the expected time", 61 0, layoutLatch.getCount()); 62 } 63 64 @Override 65 public RecyclerView.LayoutParams generateDefaultLayoutParams() { 66 return new RecyclerView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, 67 ViewGroup.LayoutParams.WRAP_CONTENT); 68 } 69 70 void assertVisibleItemPositions() { 71 int i = getChildCount(); 72 TestAdapter testAdapter = (TestAdapter) mRecyclerView.getAdapter(); 73 while (i-- > 0) { 74 View view = getChildAt(i); 75 RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) view.getLayoutParams(); 76 Item item = ((TestViewHolder) lp.mViewHolder).mBindedItem; 77 if (DEBUG) { 78 Log.d(TAG, "testing item " + i); 79 } 80 assertSame("item position in LP should match adapter value", 81 testAdapter.mItems.get(lp.getViewPosition()), item); 82 } 83 } 84 85 void layoutRange(RecyclerView.Recycler recycler, int start, 86 int end) { 87 if (DEBUG) { 88 Log.d(TAG, "will layout items from " + start + " to " + end); 89 } 90 for (int i = start; i < end; i++) { 91 if (DEBUG) { 92 Log.d(TAG, "laying out item " + i); 93 } 94 View view = recycler.getViewForPosition(i); 95 assertNotNull("view should not be null for valid position", view); 96 addView(view); 97 measureChildWithMargins(view, 0, 0); 98 layoutDecorated(view, 0, (i - start) * 10, getDecoratedMeasuredWidth(view) 99 , getDecoratedMeasuredHeight(view)); 100 } 101 } 102 } 103 104 static class Item { 105 106 int originalIndex; 107 108 final String text; 109 110 Item(int originalIndex, String text) { 111 this.originalIndex = originalIndex; 112 this.text = text; 113 } 114 } 115 116 class TestAdapter extends RecyclerView.Adapter<TestViewHolder> { 117 118 List<Item> mItems; 119 120 TestAdapter(int count) { 121 mItems = new ArrayList<Item>(count); 122 for (int i = 0; i < count; i++) { 123 mItems.add(new Item(i, "Item " + i)); 124 } 125 } 126 127 @Override 128 public TestViewHolder onCreateViewHolder(ViewGroup parent, 129 int viewType) { 130 return new TestViewHolder(new TextView(parent.getContext())); 131 } 132 133 @Override 134 public void onBindViewHolder(TestViewHolder holder, int position) { 135 final Item item = mItems.get(position); 136 ((TextView) (holder.itemView)).setText(item.text); 137 holder.mBindedItem = item; 138 } 139 140 public void deleteRangeAndNotify(final int start, final int end) throws Throwable { 141 runTestOnUiThread(new Runnable() { 142 @Override 143 public void run() { 144 for (int i = start; i < end; i++) { 145 mItems.remove(start); 146 } 147 notifyItemRangeRemoved(start, end - start); 148 } 149 }); 150 } 151 152 public void addRangeAndNotify(final int start, final int end) throws Throwable { 153 runTestOnUiThread(new Runnable() { 154 @Override 155 public void run() { 156 final int count = end - start; 157 for (int i = start; i < end; i++) { 158 mItems.add(start, new Item(i, "new item " + i)); 159 } 160 // offset others 161 for (int i = end; i < mItems.size(); i++) { 162 mItems.get(i).originalIndex += count; 163 } 164 notifyItemRangeInserted(start, count); 165 } 166 }); 167 168 } 169 170 @Override 171 public int getItemCount() { 172 return mItems.size(); 173 } 174 } 175} 176 177