BaseRecyclerViewInstrumentationTest.java revision b5f8b4fecb531aee6b359b4968409410aba90817
1d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase/* 2d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * Copyright (C) 2014 The Android Open Source Project 3d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * 4d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * Licensed under the Apache License, Version 2.0 (the "License"); 5d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * you may not use this file except in compliance with the License. 6d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * You may obtain a copy of the License at 7d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * 8d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * http://www.apache.org/licenses/LICENSE-2.0 9d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * 10d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * Unless required by applicable law or agreed to in writing, software 11d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * distributed under the License is distributed on an "AS IS" BASIS, 12d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * See the License for the specific language governing permissions and 14d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * limitations under the License. 15d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase */ 16d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 17d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haasepackage android.support.v7.widget; 18d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 19d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haaseimport android.test.ActivityInstrumentationTestCase2; 20d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haaseimport android.util.Log; 21d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haaseimport android.view.View; 22d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haaseimport android.view.ViewGroup; 23d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haaseimport android.widget.TextView; 24d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 25d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haaseimport java.util.ArrayList; 26d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haaseimport java.util.List; 27d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haaseimport java.util.concurrent.CountDownLatch; 28d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haaseimport java.util.concurrent.TimeUnit; 29d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 30d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haaseabstract public class BaseRecyclerViewInstrumentationTest extends 31d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ActivityInstrumentationTestCase2<TestActivity> { 32d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 33d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase private static final String TAG = "RecyclerViewTest"; 34d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 35b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar private boolean mDebug; 36b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 37b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar protected RecyclerView mRecyclerView; 38d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 39d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public BaseRecyclerViewInstrumentationTest() { 40b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar this(false); 41b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 42b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 43b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar public BaseRecyclerViewInstrumentationTest(boolean debug) { 44d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase super("android.support.v7.widget", TestActivity.class); 45b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar mDebug = debug; 46b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 47b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 48b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar public void removeRecyclerView() throws Throwable { 49b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar mRecyclerView = null; 50b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar runTestOnUiThread(new Runnable() { 51b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar @Override 52b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar public void run() { 53b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar getActivity().mContainer.removeAllViews(); 54b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 55b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar }); 56b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 57b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 58b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar public void setRecyclerView(final RecyclerView recyclerView) throws Throwable { 59b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar mRecyclerView = recyclerView; 60b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar runTestOnUiThread(new Runnable() { 61b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar @Override 62b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar public void run() { 63b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar getActivity().mContainer.addView(recyclerView); 64b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 65b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar }); 66b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 67b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 68b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar public void requestLayoutOnUIThread(final View view) throws Throwable { 69b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar runTestOnUiThread(new Runnable() { 70b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar @Override 71b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar public void run() { 72b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar view.requestLayout(); 73b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 74b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar }); 75b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 76b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 77b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar public void scrollBy(final int dt) throws Throwable { 78b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar runTestOnUiThread(new Runnable() { 79b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar @Override 80b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar public void run() { 81b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar if (mRecyclerView.getLayoutManager().canScrollHorizontally()) { 82b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar mRecyclerView.scrollBy(dt, 0); 83b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } else { 84b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar mRecyclerView.scrollBy(0, dt); 85b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 86b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 87b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 88b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar }); 89d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 90d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 91d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase class TestViewHolder extends RecyclerView.ViewHolder { 92d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 93d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase Item mBindedItem; 94d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 95d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public TestViewHolder(View itemView) { 96d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase super(itemView); 97d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 98d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 99d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 100d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase class TestLayoutManager extends RecyclerView.LayoutManager { 101d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 102d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase CountDownLatch layoutLatch; 103d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 104d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public void expectLayouts(int count) { 105d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase layoutLatch = new CountDownLatch(count); 106d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 107d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 108b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar public void waitForLayout(long timeout, TimeUnit timeUnit) throws Throwable { 109b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar layoutLatch.await(timeout * (mDebug ? 100 : 1), timeUnit); 110d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase assertEquals("all expected layouts should be executed at the expected time", 111d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 0, layoutLatch.getCount()); 112d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 113d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 114b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar public void assertLayoutCount(int count, String msg, long timeout) throws Throwable { 115b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar layoutLatch.await(timeout, TimeUnit.SECONDS); 116b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar assertEquals(msg, count, layoutLatch.getCount()); 117b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 118b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 119b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar public void assertNoLayout(String msg, long timeout) throws Throwable { 120b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar layoutLatch.await(timeout, TimeUnit.SECONDS); 121b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar assertFalse(msg, layoutLatch.getCount() == 0); 122b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 123b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 124b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar public void waitForLayout(long timeout) throws Throwable { 125b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar waitForLayout(timeout, TimeUnit.SECONDS); 126b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 127b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 128d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 129d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public RecyclerView.LayoutParams generateDefaultLayoutParams() { 130d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase return new RecyclerView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, 131d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ViewGroup.LayoutParams.WRAP_CONTENT); 132d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 133d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 134d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase void assertVisibleItemPositions() { 135d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase int i = getChildCount(); 136d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase TestAdapter testAdapter = (TestAdapter) mRecyclerView.getAdapter(); 137d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase while (i-- > 0) { 138d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase View view = getChildAt(i); 139d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) view.getLayoutParams(); 140d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase Item item = ((TestViewHolder) lp.mViewHolder).mBindedItem; 141b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar if (mDebug) { 142d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase Log.d(TAG, "testing item " + i); 143d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 144d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase assertSame("item position in LP should match adapter value", 145d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase testAdapter.mItems.get(lp.getViewPosition()), item); 146d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 147d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 148d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 149b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar RecyclerView.LayoutParams getLp(View v) { 150b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar return (RecyclerView.LayoutParams) v.getLayoutParams(); 151b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 152b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 153d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase void layoutRange(RecyclerView.Recycler recycler, int start, 154d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase int end) { 155b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar if (mDebug) { 156d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase Log.d(TAG, "will layout items from " + start + " to " + end); 157d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 158d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase for (int i = start; i < end; i++) { 159b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar if (mDebug) { 160d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase Log.d(TAG, "laying out item " + i); 161d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 162d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase View view = recycler.getViewForPosition(i); 163b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar assertNotNull("view should not be null for valid position. " 164b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar + "got null view at position " + i, view); 165b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar if (!getLp(view).isItemRemoved()) { 166b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar addView(view); 167b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 168b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 169d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase measureChildWithMargins(view, 0, 0); 170d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase layoutDecorated(view, 0, (i - start) * 10, getDecoratedMeasuredWidth(view) 171d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase , getDecoratedMeasuredHeight(view)); 172d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 173d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 174d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 175d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 176d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase static class Item { 177d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 178d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase int originalIndex; 179d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 180d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase final String text; 181d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 182d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase Item(int originalIndex, String text) { 183d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase this.originalIndex = originalIndex; 184d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase this.text = text; 185d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 186d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 187d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 188d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase class TestAdapter extends RecyclerView.Adapter<TestViewHolder> { 189d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 190d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase List<Item> mItems; 191d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 192d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase TestAdapter(int count) { 193d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mItems = new ArrayList<Item>(count); 194d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase for (int i = 0; i < count; i++) { 195d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mItems.add(new Item(i, "Item " + i)); 196d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 197d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 198d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 199d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 200d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public TestViewHolder onCreateViewHolder(ViewGroup parent, 201d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase int viewType) { 202d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase return new TestViewHolder(new TextView(parent.getContext())); 203d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 204d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 205d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 206d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public void onBindViewHolder(TestViewHolder holder, int position) { 207d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase final Item item = mItems.get(position); 208d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase ((TextView) (holder.itemView)).setText(item.text); 209d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase holder.mBindedItem = item; 210d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 211d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 212b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar public void deleteAndNotify(final int start, final int count) throws Throwable { 213b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar deleteAndNotify(new int[]{start, count}); 214b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 215b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 216b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar /** 217b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar * Deletes items in the given ranges. 218b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar * <p> 219b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar * Note that each operation affects the one after so you should offset them properly. 220b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar * <p> 221b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar * For example, if adapter has 5 items (A,B,C,D,E), and then you call this method with 222b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar * <code>[1, 2],[2, 1]</code>, it will first delete items B,C and the new adapter will be 223b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar * A D E. Then it will delete 2,1 which means it will delete E. 224b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar */ 225b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar public void deleteAndNotify(final int[]... startCountTuples) throws Throwable { 226d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase runTestOnUiThread(new Runnable() { 227d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 228d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public void run() { 229b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar for (int t = 0; t < startCountTuples.length; t++) { 230b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar int[] tuple = startCountTuples[t]; 231b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar for (int i = 0; i < tuple[1]; i++) { 232b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar mItems.remove(tuple[0]); 233b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 234b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar notifyItemRangeRemoved(tuple[0], tuple[1]); 235d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 236b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 237d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 238d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase }); 239d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 240d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 241b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar public void addAndNotify(final int start, final int count) throws Throwable { 242b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar addAndNotify(new int[]{start, count}); 243b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 244b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 245b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar public void addAndNotify(final int[]... startCountTuples) throws Throwable { 246d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase runTestOnUiThread(new Runnable() { 247d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 248d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public void run() { 249b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar for (int t = 0; t < startCountTuples.length; t++) { 250b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar int[] tuple = startCountTuples[t]; 251b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar for (int i = 0; i < tuple[1]; i++) { 252b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar mItems.add(tuple[0], new Item(i, "new item " + i)); 253b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 254b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar // offset others 255b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar for (int i = tuple[0] + tuple[1]; i < mItems.size(); i++) { 256b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar mItems.get(i).originalIndex += tuple[1]; 257b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 258b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar notifyItemRangeInserted(tuple[0], tuple[1]); 259d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 260b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 261d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 262d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase }); 263d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 264d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 265d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase @Override 266d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase public int getItemCount() { 267d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase return mItems.size(); 268d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 269d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 270b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar}