1edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar/* 2edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar * Copyright (C) 2014 The Android Open Source Project 3edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar * 4edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar * Licensed under the Apache License, Version 2.0 (the "License"); 5edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar * you may not use this file except in compliance with the License. 6edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar * You may obtain a copy of the License at 7edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar * 8edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar * http://www.apache.org/licenses/LICENSE-2.0 9edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar * 10edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar * Unless required by applicable law or agreed to in writing, software 11edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar * distributed under the License is distributed on an "AS IS" BASIS, 12edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar * See the License for the specific language governing permissions and 14edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar * limitations under the License. 15edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar */ 16edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar 17edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyarpackage android.support.v7.widget; 18edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar 19c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyarimport android.os.Parcel; 20c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyarimport android.os.Parcelable; 21edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyarimport android.test.AndroidTestCase; 22abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyarimport android.util.Log; 23edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyarimport android.view.View; 24edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyarimport android.view.ViewGroup; 25edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyarimport android.widget.TextView; 26edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar 27c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyarimport java.util.UUID; 28c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar 29d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haasepublic class RecyclerViewBasicTest extends AndroidTestCase { 30edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar 31edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar RecyclerView mRecyclerView; 32edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar 33edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar @Override 34edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar protected void setUp() throws Exception { 35edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar super.setUp(); 36edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar mRecyclerView = new RecyclerView(mContext); 37edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar } 38edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar 39edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar public void testMeasureWithoutLayoutManager() { 40abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar measure(); 41edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar } 42edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar 43edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar private void measure() { 44edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar mRecyclerView.measure(View.MeasureSpec.AT_MOST | 320, View.MeasureSpec.AT_MOST | 240); 45edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar } 46edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar 47edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar private void layout() { 48edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar mRecyclerView.layout(0, 0, 320, 320); 49edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar } 50edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar 51abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar private void focusSearch() { 52abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar mRecyclerView.focusSearch(1); 53edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar } 54edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar 55abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar public void testLayoutWithoutAdapter() throws InterruptedException { 56edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar MockLayoutManager layoutManager = new MockLayoutManager(); 57edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar mRecyclerView.setLayoutManager(layoutManager); 58abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar layout(); 59edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar assertEquals("layout manager should not be called if there is no adapter attached", 60edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar 0, layoutManager.mLayoutCount); 61edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar } 62edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar 63abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar public void testLayoutWithoutLayoutManager() throws InterruptedException { 64abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar mRecyclerView.setAdapter(new MockAdapter(20)); 65abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar measure(); 66abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar layout(); 67abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar } 68abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar 69abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar public void testFocusWithoutLayoutManager() throws InterruptedException { 70abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar mRecyclerView.setAdapter(new MockAdapter(20)); 71abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar measure(); 72abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar layout(); 73abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar focusSearch(); 74abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar } 75abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar 76abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar public void testScrollWithoutLayoutManager() throws InterruptedException { 77abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar mRecyclerView.setAdapter(new MockAdapter(20)); 78abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar measure(); 79abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar layout(); 80abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar mRecyclerView.scrollBy(10, 10); 81abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar } 82abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar 83abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar public void testSmoothScrollWithoutLayoutManager() throws InterruptedException { 84abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar mRecyclerView.setAdapter(new MockAdapter(20)); 85abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar measure(); 86abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar layout(); 87abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar mRecyclerView.smoothScrollBy(10, 10); 88abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar } 89abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar 90abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar public void testScrollToPositionWithoutLayoutManager() throws InterruptedException { 91abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar mRecyclerView.setAdapter(new MockAdapter(20)); 92abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar measure(); 93abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar layout(); 94abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar mRecyclerView.scrollToPosition(5); 95abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar } 96abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar 97abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar public void testSmoothScrollToPositionWithoutLayoutManager() throws InterruptedException { 98abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar mRecyclerView.setAdapter(new MockAdapter(20)); 99abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar measure(); 100abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar layout(); 101abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar mRecyclerView.smoothScrollToPosition(5); 102abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar } 103abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar 104edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar public void testLayout() throws InterruptedException { 105edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar MockLayoutManager layoutManager = new MockLayoutManager(); 106edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar mRecyclerView.setLayoutManager(layoutManager); 107edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar mRecyclerView.setAdapter(new MockAdapter(3)); 108edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar layout(); 109edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar assertEquals("when both layout manager and activity is set, recycler view should call" 110edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar + " layout manager's layout method", 1, layoutManager.mLayoutCount); 111edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar } 112edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar 113edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar public void testObservingAdapters() { 114edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar MockAdapter adapterOld = new MockAdapter(1); 115edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar mRecyclerView.setAdapter(adapterOld); 116edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar assertTrue("attached adapter should have observables", adapterOld.hasObservers()); 117edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar 118edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar MockAdapter adapterNew = new MockAdapter(2); 119edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar mRecyclerView.setAdapter(adapterNew); 120edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar assertFalse("detached adapter should lose observable", adapterOld.hasObservers()); 121edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar assertTrue("new adapter should have observers", adapterNew.hasObservers()); 122edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar 123edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar mRecyclerView.setAdapter(null); 124edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar assertNull("adapter should be removed successfully", mRecyclerView.getAdapter()); 125edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar assertFalse("when adapter is removed, observables should be removed too", 126edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar adapterNew.hasObservers()); 127edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar } 128edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar 129edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar public void testAdapterChangeCallbacks() { 130edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar MockLayoutManager layoutManager = new MockLayoutManager(); 131edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar mRecyclerView.setLayoutManager(layoutManager); 132edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar MockAdapter adapterOld = new MockAdapter(1); 133edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar mRecyclerView.setAdapter(adapterOld); 134edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar layoutManager.assertPrevNextAdapters(null, adapterOld); 135edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar 136edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar MockAdapter adapterNew = new MockAdapter(2); 137edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar mRecyclerView.setAdapter(adapterNew); 138edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar layoutManager.assertPrevNextAdapters("switching adapters should trigger correct callbacks" 139edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar , adapterOld, adapterNew); 140edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar 141edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar mRecyclerView.setAdapter(null); 142edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar layoutManager.assertPrevNextAdapters( 143edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar "Setting adapter null should trigger correct callbacks", 144edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar adapterNew, null); 145edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar } 146edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar 147c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar public void testSavedStateWithStatelessLayoutManager() throws InterruptedException { 148c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar mRecyclerView.setLayoutManager(new MockLayoutManager() { 149c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar @Override 150c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar public Parcelable onSaveInstanceState() { 151c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar return null; 152c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar } 153c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar }); 154c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar mRecyclerView.setAdapter(new MockAdapter(3)); 155c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar Parcel parcel = Parcel.obtain(); 156c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar String parcelSuffix = UUID.randomUUID().toString(); 157c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar Parcelable savedState = mRecyclerView.onSaveInstanceState(); 158c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar savedState.writeToParcel(parcel, 0); 159c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar parcel.writeString(parcelSuffix); 160c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar 161c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar // reset position for reading 162c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar parcel.setDataPosition(0); 163c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar RecyclerView restored = new RecyclerView(mContext); 164c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar restored.setLayoutManager(new MockLayoutManager()); 165c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar mRecyclerView.setAdapter(new MockAdapter(3)); 166c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar // restore 167c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar savedState = RecyclerView.SavedState.CREATOR.createFromParcel(parcel); 168c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar restored.onRestoreInstanceState(savedState); 169c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar 170c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar assertEquals("Parcel reading should not go out of bounds", parcelSuffix, 171c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar parcel.readString()); 172c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar assertEquals("When unmarshalling, all of the parcel should be read", 0, parcel.dataAvail()); 173c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar 174c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar } 175c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar 176c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar public void testSavedState() throws InterruptedException { 177c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar MockLayoutManager mlm = new MockLayoutManager(); 178c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar mRecyclerView.setLayoutManager(mlm); 179c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar mRecyclerView.setAdapter(new MockAdapter(3)); 180c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar layout(); 181c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar Parcelable savedState = mRecyclerView.onSaveInstanceState(); 182c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar // we append a suffix to the parcelable to test out of bounds 183c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar String parcelSuffix = UUID.randomUUID().toString(); 184c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar Parcel parcel = Parcel.obtain(); 185c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar savedState.writeToParcel(parcel, 0); 186c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar parcel.writeString(parcelSuffix); 187c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar 188c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar // reset for reading 189c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar parcel.setDataPosition(0); 190c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar // re-create 191c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar savedState = RecyclerView.SavedState.CREATOR.createFromParcel(parcel); 192c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar 193c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar RecyclerView restored = new RecyclerView(mContext); 194c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar MockLayoutManager mlmRestored = new MockLayoutManager(); 195c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar restored.setLayoutManager(mlmRestored); 196c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar restored.setAdapter(new MockAdapter(3)); 197c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar restored.onRestoreInstanceState(savedState); 198c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar 199c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar assertEquals("Parcel reading should not go out of bounds", parcelSuffix, 200c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar parcel.readString()); 201c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar assertEquals("When unmarshalling, all of the parcel should be read", 0, parcel.dataAvail()); 202c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar assertEquals("uuid in layout manager should be preserved properly", mlm.mUuid, 203c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar mlmRestored.mUuid); 204c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar assertNotSame("stateless parameter should not be preserved", mlm.mLayoutCount, 205c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar mlmRestored.mLayoutCount); 206c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar layout(); 207c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar } 208c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar 209c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar static class MockLayoutManager extends RecyclerView.LayoutManager { 210edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar 211edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar int mLayoutCount = 0; 212edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar 213edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar int mAdapterChangedCount = 0; 214edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar 215edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar RecyclerView.Adapter mPrevAdapter; 216edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar 217edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar RecyclerView.Adapter mNextAdapter; 218edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar 219c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar String mUuid = UUID.randomUUID().toString(); 220c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar 221edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar @Override 222edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar public void onAdapterChanged(RecyclerView.Adapter oldAdapter, 223edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar RecyclerView.Adapter newAdapter) { 224edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar super.onAdapterChanged(oldAdapter, newAdapter); 225edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar mPrevAdapter = oldAdapter; 226edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar mNextAdapter = newAdapter; 227edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar mAdapterChangedCount++; 228edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar } 229edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar 230edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar @Override 231d4a794983364c7b1801638abc7f332abee12b6e6Yigit Boyar public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) { 232edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar mLayoutCount += 1; 233edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar } 234edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar 235edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar @Override 236c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar public Parcelable onSaveInstanceState() { 237c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar LayoutManagerSavedState lss = new LayoutManagerSavedState(); 238c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar lss.mUuid = mUuid; 239c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar return lss; 240c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar } 241c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar 242c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar @Override 243c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar public void onRestoreInstanceState(Parcelable state) { 244c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar super.onRestoreInstanceState(state); 245c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar if (state instanceof LayoutManagerSavedState) { 246c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar mUuid = ((LayoutManagerSavedState) state).mUuid; 247c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar } 248c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar } 249c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar 250c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar @Override 251edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar public RecyclerView.LayoutParams generateDefaultLayoutParams() { 252edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar return new RecyclerView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, 253edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar ViewGroup.LayoutParams.WRAP_CONTENT); 254edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar } 255edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar 256edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar public void assertPrevNextAdapters(String message, RecyclerView.Adapter prevAdapter, 257edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar RecyclerView.Adapter nextAdapter) { 258edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar assertSame(message, prevAdapter, mPrevAdapter); 259edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar assertSame(message, nextAdapter, mNextAdapter); 260edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar } 261edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar 262edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar public void assertPrevNextAdapters(RecyclerView.Adapter prevAdapter, 263edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar RecyclerView.Adapter nextAdapter) { 264edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar assertPrevNextAdapters("Adapters from onAdapterChanged callback should match", 265edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar prevAdapter, nextAdapter); 266edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar } 267bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar 268bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar @Override 269bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar public int scrollHorizontallyBy(int dx, RecyclerView.Recycler recycler, 270bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar RecyclerView.State state) { 271bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar return dx; 272bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar } 273bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar 274bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar @Override 275bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, 276bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar RecyclerView.State state) { 277bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar return dy; 278bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar } 279bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar 280bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar @Override 281bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar public boolean canScrollHorizontally() { 282bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar return true; 283bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar } 284bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar 285bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar @Override 286bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar public boolean canScrollVertically() { 287bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar return true; 288bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar } 289edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar } 290edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar 291c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar static class LayoutManagerSavedState implements Parcelable { 292c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar 293c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar String mUuid; 294c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar 295c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar public LayoutManagerSavedState(Parcel in) { 296c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar mUuid = in.readString(); 297c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar } 298c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar 299c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar public LayoutManagerSavedState() { 300c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar 301c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar } 302c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar 303c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar @Override 304c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar public int describeContents() { 305c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar return 0; 306c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar } 307c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar 308c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar @Override 309c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar public void writeToParcel(Parcel dest, int flags) { 310c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar dest.writeString(mUuid); 311c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar } 312c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar 313c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar public static final Parcelable.Creator<LayoutManagerSavedState> CREATOR 314c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar = new Parcelable.Creator<LayoutManagerSavedState>() { 315c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar @Override 316c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar public LayoutManagerSavedState createFromParcel(Parcel in) { 317c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar return new LayoutManagerSavedState(in); 318c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar } 319c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar 320c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar @Override 321c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar public LayoutManagerSavedState[] newArray(int size) { 322c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar return new LayoutManagerSavedState[size]; 323c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar } 324c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar }; 325c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar } 326c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar 327c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar static class MockAdapter extends RecyclerView.Adapter { 328edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar 329edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar private int mCount = 0; 330edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar 331d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 332c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar MockAdapter(int count) { 333edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar this.mCount = count; 334edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar } 335edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar 336edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar @Override 337edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 338edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar return new MockViewHolder(new TextView(parent.getContext())); 339edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar } 340edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar 341edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar @Override 342edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 343edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar 344edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar } 345edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar 346edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar @Override 347edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar public int getItemCount() { 348edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar return mCount; 349edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar } 350d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 351d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase void removeItems(int start, int count) { 352d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mCount -= count; 353d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase notifyItemRangeRemoved(start, count); 354d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 355d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 356d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase void addItems(int start, int count) { 357d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mCount += count; 358d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase notifyItemRangeInserted(start, count); 359d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 360edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar } 361edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar 362c30b4fceb76f45348c20f8b15096e1e13ff0c42fYigit Boyar static class MockViewHolder extends RecyclerView.ViewHolder { 363115ba0c7b2a14aa4cd0273952195e1d8f6468f87Yigit Boyar public Object mItem; 364edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar public MockViewHolder(View itemView) { 365edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar super(itemView); 366edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar } 367edc25dd683986a905790b0e9ef124165b6dd8004Yigit Boyar } 368b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar}