RecyclerViewAnimationsTest.java revision 11b7cfea15306c0d6e4ed7da09f7698df01695df
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
19b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyarimport android.content.Context;
20888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyarimport android.graphics.Canvas;
21b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyarimport android.util.AttributeSet;
22b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyarimport android.util.Log;
23b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyarimport android.view.View;
24b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
2511b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyarimport java.util.ArrayList;
2611b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyarimport java.util.HashSet;
2711b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyarimport java.util.List;
2811b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyarimport java.util.Map;
2911b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyarimport java.util.Set;
30888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyarimport java.util.concurrent.CountDownLatch;
31d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haaseimport java.util.concurrent.TimeUnit;
32d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
33d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haasepublic class RecyclerViewAnimationsTest extends BaseRecyclerViewInstrumentationTest {
34d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
35b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar    private static final boolean DEBUG = false;
36b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
37b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar    private static final String TAG = "RecyclerViewAnimationsTest";
38b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
39b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar    Throwable mainThreadException;
40b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
41b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar    AnimationLayoutManager mLayoutManager;
42b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
43b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar    TestAdapter mTestAdapter;
44b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
45b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar    public RecyclerViewAnimationsTest() {
46b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        super(DEBUG);
47b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar    }
48b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
49b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar    @Override
50b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar    protected void setUp() throws Exception {
51b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        super.setUp();
52b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar    }
53b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
54b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar    void checkForMainThreadException() throws Throwable {
55b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        if (mainThreadException != null) {
56b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            throw mainThreadException;
57b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        }
58b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar    }
59b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
60b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar    RecyclerView setupBasic(int itemCount) throws Throwable {
61b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        return setupBasic(itemCount, 0, itemCount);
62b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar    }
63b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
64b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar    RecyclerView setupBasic(int itemCount, int firstLayoutStartIndex, int firstLayoutItemCount)
65b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            throws Throwable {
6611b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar        return setupBasic(itemCount, firstLayoutStartIndex, firstLayoutItemCount, null);
6711b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar    }
6811b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar
6911b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar    RecyclerView setupBasic(int itemCount, int firstLayoutStartIndex, int firstLayoutItemCount,
7011b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar            TestAdapter testAdapter)
7111b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar            throws Throwable {
72888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar        final TestRecyclerView recyclerView = new TestRecyclerView(getActivity());
73b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        recyclerView.setHasFixedSize(true);
7411b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar        if (testAdapter == null) {
7511b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar            mTestAdapter = new TestAdapter(itemCount);
7611b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar        } else {
7711b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar            mTestAdapter = testAdapter;
7811b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar        }
79b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        recyclerView.setAdapter(mTestAdapter);
80b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        mLayoutManager = new AnimationLayoutManager();
81b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        recyclerView.setLayoutManager(mLayoutManager);
82b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        mLayoutManager.mOnLayoutCallbacks.mLayoutMin = firstLayoutStartIndex;
83b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        mLayoutManager.mOnLayoutCallbacks.mLayoutItemCount = firstLayoutItemCount;
84b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
85b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        mLayoutManager.expectLayouts(1);
86888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar        recyclerView.expectDraw(1);
87b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        setRecyclerView(recyclerView);
88b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        mLayoutManager.waitForLayout(2);
89888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar        recyclerView.waitForDraw(1);
90888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar        mLayoutManager.mOnLayoutCallbacks.reset();
91b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        return recyclerView;
92b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar    }
93b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
9411b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar    public void getItemForDeletedViewTest() throws Throwable {
9511b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar        testGetItemForDeletedView(false);
9611b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar        testGetItemForDeletedView(true);
9711b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar    }
9811b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar
9911b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar    public void testGetItemForDeletedView(boolean stableIds) throws Throwable {
10011b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar        final Set<Integer> itemViewTypeQueries = new HashSet<Integer>();
10111b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar        final Set<Integer> itemIdQueries = new HashSet<Integer>();
10211b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar        TestAdapter adapter = new TestAdapter(10) {
10311b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar            @Override
10411b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar            public int getItemViewType(int position) {
10511b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar                itemViewTypeQueries.add(position);
10611b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar                return super.getItemViewType(position);
10711b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar            }
10811b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar
10911b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar            @Override
11011b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar            public long getItemId(int position) {
11111b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar                itemIdQueries.add(position);
11211b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar                return mItems.get(position).mId;
11311b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar            }
11411b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar        };
11511b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar        adapter.setHasStableIds(stableIds);
11611b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar        setupBasic(10, 0, 10, adapter);
11711b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar        assertEquals("getItemViewType for all items should be called", 10,
11811b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar                itemViewTypeQueries.size());
11911b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar        if (adapter.hasStableIds()) {
12011b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar            assertEquals("getItemId should be called when adapter has stable ids", 10,
12111b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar                    itemIdQueries.size());
12211b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar        } else {
12311b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar            assertEquals("getItemId should not be called when adapter does not have stable ids", 0,
12411b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar                    itemIdQueries.size());
12511b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar        }
12611b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar        itemViewTypeQueries.clear();
12711b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar        itemIdQueries.clear();
12811b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar        mLayoutManager.expectLayouts(2);
12911b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar        // delete last two
13011b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar        final int deleteStart = 8;
13111b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar        final int deleteCount = adapter.getItemCount() - deleteStart;
13211b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar        adapter.deleteAndNotify(deleteStart, deleteCount);
13311b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar        mLayoutManager.waitForLayout(2);
13411b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar        for (int i = 0; i < deleteStart; i++) {
13511b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar            assertTrue("getItemViewType for existing item " + i + " should be called",
13611b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar                    itemViewTypeQueries.contains(i));
13711b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar            if (adapter.hasStableIds()) {
13811b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar                assertTrue("getItemId for existing item " + i
13911b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar                        + " should be called when adapter has stable ids",
14011b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar                        itemIdQueries.contains(i));
14111b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar            }
14211b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar        }
14311b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar        for (int i = deleteStart; i < deleteStart + deleteCount; i++) {
14411b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar            assertFalse("getItemViewType for deleted item " + i + " SHOULD NOT be called",
14511b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar                    itemViewTypeQueries.contains(i));
14611b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar            if (adapter.hasStableIds()) {
14711b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar                assertTrue("getItemId for deleted item " + i + " SHOULD NOT be called",
14811b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar                        itemIdQueries.contains(i));
14911b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar            }
15011b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar        }
15111b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar    }
15211b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar
153b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar    public void testAddInvisibleAndVisible() throws Throwable {
154b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        setupBasic(10, 1, 7);
155b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        mLayoutManager.expectLayouts(2);
156b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        mLayoutManager.mOnLayoutCallbacks.setExpectedItemCounts(10, 12);
157b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        mTestAdapter.addAndNotify(0, 1);// add a new item 0 // invisible
158b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        mTestAdapter.addAndNotify(7, 1);// add a new item after 5th (old 5, new 6)
159b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        mLayoutManager.waitForLayout(2);
160b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar    }
161b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
162b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar    public void testAddInvisible() throws Throwable {
163b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        setupBasic(10, 1, 7);
164b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        mLayoutManager.expectLayouts(1);
165b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        mLayoutManager.mOnLayoutCallbacks.setExpectedItemCounts(10, 12);
166b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        mTestAdapter.addAndNotify(0, 1);// add a new item 0
167b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        mTestAdapter.addAndNotify(8, 1);// add a new item after 6th (old 6, new 7)
168b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        mLayoutManager.waitForLayout(2);
169b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar    }
170b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
171b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar    public void testBasicAdd() throws Throwable {
172b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        setupBasic(10);
173b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        mLayoutManager.expectLayouts(2);
174b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        setExpectedItemCounts(10, 13);
175b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        mTestAdapter.addAndNotify(2, 3);
176b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        mLayoutManager.waitForLayout(2);
177b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar    }
178b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
179888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar    public TestRecyclerView getTestRecyclerView() {
180888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar        return (TestRecyclerView) mRecyclerView;
181888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar    }
182888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar
183888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar    public void testRemoveScrapInvalidate() throws Throwable {
184888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar        setupBasic(10);
185888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar        TestRecyclerView testRecyclerView = getTestRecyclerView();
186888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar        mLayoutManager.expectLayouts(1);
187888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar        testRecyclerView.expectDraw(1);
188888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar        runTestOnUiThread(new Runnable() {
189888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar            @Override
190888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar            public void run() {
191888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar                mTestAdapter.mItems.clear();
192888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar                mTestAdapter.notifyDataSetChanged();
193888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar            }
194888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar        });
195888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar        mLayoutManager.waitForLayout(2);
196888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar        testRecyclerView.waitForDraw(2);
197888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar    }
198888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar
199b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar    public void testDeleteVisibleAndInvisible() throws Throwable {
200b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        setupBasic(11, 3, 5); //layout items  3 4 5 6 7
201b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        mLayoutManager.expectLayouts(2);
202b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        setLayoutRange(3, 6); //layout previously invisible child 10 from end of the list
203b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        setExpectedItemCounts(9, 8);
204b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        mTestAdapter.deleteAndNotify(new int[]{4, 1}, new int[]{7, 2});// delete items 4, 8, 9
205b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        mLayoutManager.waitForLayout(2);
206b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar    }
207b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
208b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar    private void setLayoutRange(int start, int count) {
209b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        mLayoutManager.mOnLayoutCallbacks.mLayoutMin = start;
210b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        mLayoutManager.mOnLayoutCallbacks.mLayoutItemCount = count;
211b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar    }
212b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
213b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar    private void setExpectedItemCounts(int preLayout, int postLayout) {
214b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        mLayoutManager.mOnLayoutCallbacks.setExpectedItemCounts(preLayout, postLayout);
215b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar    }
216b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
217b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar    public void testDeleteInvisible() throws Throwable {
218b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        setupBasic(10, 1, 7);
219b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        mLayoutManager.expectLayouts(1);
220b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        mLayoutManager.mOnLayoutCallbacks.setExpectedItemCounts(8, 8);
221b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        mTestAdapter.deleteAndNotify(0, 1);// delete item id 0
222b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        mTestAdapter.deleteAndNotify(7, 1);// delete item id 8
223b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        mLayoutManager.waitForLayout(2);
224b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar    }
225b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
226b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar    public void testBasicDelete() throws Throwable {
227b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        setupBasic(10);
228b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        final OnLayoutCallbacks callbacks = new OnLayoutCallbacks() {
229d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            @Override
230b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            public void postDispatchLayout() {
231b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                // verify this only in first layout
232b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                assertEquals("deleted views should still be children of RV",
233b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                        mLayoutManager.getChildCount() + mDeletedViewCount
234b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                        , mRecyclerView.getChildCount());
235b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            }
236d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
237b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            @Override
238b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            void afterPreLayout(RecyclerView.Recycler recycler,
239b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                    AnimationLayoutManager layoutManager,
240b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                    RecyclerView.State state) {
241b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                super.afterPreLayout(recycler, layoutManager, state);
242b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                mLayoutItemCount = 3;
243b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                mLayoutMin = 0;
244d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            }
245d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        };
246b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        callbacks.mLayoutItemCount = 10;
247b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        callbacks.setExpectedItemCounts(10, 3);
248b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        mLayoutManager.setOnLayoutCallbacks(callbacks);
249b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
250b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        mLayoutManager.expectLayouts(2);
251b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        mTestAdapter.deleteAndNotify(0, 7);
252b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        mLayoutManager.waitForLayout(2);
253b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        callbacks.reset();// when animations end another layout will happen
254b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar    }
255b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
256b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
257b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar    class AnimationLayoutManager extends TestLayoutManager {
258b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
259b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        OnLayoutCallbacks mOnLayoutCallbacks = new OnLayoutCallbacks() {
260b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        };
261b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
262b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        @Override
263b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        public boolean supportsItemAnimations() {
264b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            return true;
265b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        }
266b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
267b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        @Override
268b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        public void expectLayouts(int count) {
269b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            super.expectLayouts(count);
270b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            mOnLayoutCallbacks.mLayoutCount = 0;
271b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        }
272b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
273b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        public void setOnLayoutCallbacks(OnLayoutCallbacks onLayoutCallbacks) {
274b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            mOnLayoutCallbacks = onLayoutCallbacks;
275b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        }
276b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
277b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        @Override
278b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        public final void onLayoutChildren(RecyclerView.Recycler recycler,
279b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                RecyclerView.State state) {
280b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            try {
281b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                mOnLayoutCallbacks.onLayoutChildren(recycler, this, state);
282b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            } finally {
283b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                layoutLatch.countDown();
284d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            }
285b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        }
286b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
287b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
288b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        public void onPostDispatchLayout() {
289b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            mOnLayoutCallbacks.postDispatchLayout();
290b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        }
291b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
292b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        @Override
293b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        public void waitForLayout(long timeout, TimeUnit timeUnit) throws Throwable {
294b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            super.waitForLayout(timeout, timeUnit);
295b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            checkForMainThreadException();
296b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        }
297d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
298d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
299b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar    abstract class OnLayoutCallbacks {
300b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
301b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        int mLayoutMin = Integer.MIN_VALUE;
302b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
303b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        int mLayoutItemCount = Integer.MAX_VALUE;
304b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
305b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        int expectedPreLayoutItemCount = -1;
306b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
307b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        int expectedPostLayoutItemCount = -1;
308b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
309b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        private int mLayoutCount;
310b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
311b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        int mDeletedViewCount;
312b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
313b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        void setExpectedItemCounts(int preLayout, int postLayout) {
314b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            expectedPreLayoutItemCount = preLayout;
315b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            expectedPostLayoutItemCount = postLayout;
316b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        }
317b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
318b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        void reset() {
319b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            mLayoutCount = 0;
320b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            mLayoutMin = Integer.MIN_VALUE;
321b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            mLayoutItemCount = Integer.MAX_VALUE;
322b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            expectedPreLayoutItemCount = -1;
323b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            expectedPostLayoutItemCount = -1;
324b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        }
325b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
326b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        void beforePreLayout(RecyclerView.Recycler recycler,
327b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                AnimationLayoutManager lm, RecyclerView.State state) {
328b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            mDeletedViewCount = 0;
329b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            for (int i = 0; i < lm.getChildCount(); i++) {
330b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                View v = lm.getChildAt(i);
331b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                if (lm.getLp(v).isItemRemoved()) {
332b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                    mDeletedViewCount++;
333b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                }
334b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            }
335b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        }
336b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
337b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        void doLayout(RecyclerView.Recycler recycler, AnimationLayoutManager lm,
338b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                RecyclerView.State state) {
339b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            if (DEBUG) {
340b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                Log.d(TAG, "item count " + state.getItemCount());
341b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            }
342b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            lm.detachAndScrapAttachedViews(recycler);
343b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            final int start = mLayoutMin == Integer.MIN_VALUE ? 0 : mLayoutMin;
344b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            final int count = mLayoutItemCount
345b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                    == Integer.MAX_VALUE ? state.getItemCount() : mLayoutItemCount;
346b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            lm.layoutRange(recycler, start, start + count);
347b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            assertEquals("correct # of children should be laid out",
348b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                    count - (inPreLayout() ? mDeletedViewCount : 0), lm.getChildCount());
349b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            if (!inPreLayout()) { // may not be the correct check
350b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                lm.assertVisibleItemPositions();
351b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            }
352b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        }
353b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
354b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        void onLayoutChildren(RecyclerView.Recycler recycler, AnimationLayoutManager lm,
355b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                RecyclerView.State state) {
356b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
357b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            if (mLayoutCount == 0) {
358b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                if (expectedPreLayoutItemCount != -1) {
359b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                    assertEquals("on pre layout, state should return abstracted adapter size",
360b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                            expectedPreLayoutItemCount, state.getItemCount());
361b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                }
362b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                beforePreLayout(recycler, lm, state);
363b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            } else if (mLayoutCount == 1) {
364b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                if (expectedPostLayoutItemCount != -1) {
365b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                    assertEquals("on post layout, state should return real adapter size",
366b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                            expectedPostLayoutItemCount, state.getItemCount());
367b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                }
368b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                beforePostLayout(recycler, lm, state);
369b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            }
370b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            doLayout(recycler, lm, state);
371b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            if (mLayoutCount == 0) {
372b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                afterPreLayout(recycler, lm, state);
373b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            } else if (mLayoutCount == 1) {
374b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                afterPostLayout(recycler, lm, state);
375b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            }
376b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            mLayoutCount++;
377b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        }
378b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
379b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        void afterPreLayout(RecyclerView.Recycler recycler, AnimationLayoutManager layoutManager,
380b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                RecyclerView.State state) {
381b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        }
382b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
383b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        void beforePostLayout(RecyclerView.Recycler recycler, AnimationLayoutManager layoutManager,
384b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                RecyclerView.State state) {
385b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        }
386b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
387b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        void afterPostLayout(RecyclerView.Recycler recycler, AnimationLayoutManager layoutManager,
388b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                RecyclerView.State state) {
389b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        }
390b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
391b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        void postDispatchLayout() {
392b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        }
393b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
394b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        boolean inPreLayout() {
395b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            return mLayoutCount == 0;
396b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        }
397b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar    }
398b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
399b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar    class TestRecyclerView extends RecyclerView {
40011b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar
401888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar        CountDownLatch drawLatch;
402b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
403b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        public TestRecyclerView(Context context) {
404b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            super(context);
405b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        }
406b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
407b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        public TestRecyclerView(Context context, AttributeSet attrs) {
408b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            super(context, attrs);
409b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        }
410b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
411b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        public TestRecyclerView(Context context, AttributeSet attrs, int defStyle) {
412b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            super(context, attrs, defStyle);
413b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        }
414b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
415888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar        public void expectDraw(int count) {
416888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar            drawLatch = new CountDownLatch(count);
417888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar        }
418888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar
419888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar        public void waitForDraw(long timeout) throws Throwable {
420888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar            drawLatch.await(timeout * (DEBUG ? 100 : 1), TimeUnit.SECONDS);
421888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar            assertEquals("all expected draws should happen at the expected time frame",
422888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar                    0, drawLatch.getCount());
423888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar        }
424888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar
425888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar        @Override
426888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar        protected void dispatchDraw(Canvas canvas) {
427888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar            super.dispatchDraw(canvas);
428888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar            if (drawLatch != null) {
429888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar                drawLatch.countDown();
430888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar            }
431888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar        }
432888c70abaa77e15458c366b8d27835d176dcc546Yigit Boyar
433b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        @Override
434b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        void dispatchLayout() {
435b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            try {
436b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                super.dispatchLayout();
437b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                if (getLayoutManager() instanceof AnimationLayoutManager) {
438b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                    ((AnimationLayoutManager) getLayoutManager()).onPostDispatchLayout();
439b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                }
440b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            } catch (Throwable t) {
441b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                postExceptionToInstrumentation(t);
442b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            }
443b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
444b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        }
445b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
446b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        private void postExceptionToInstrumentation(Throwable t) {
447b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            if (DEBUG) {
448b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                Log.e(TAG, "captured exception on main thread", t);
449b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            }
450b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            mainThreadException = t;
451b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            if (mLayoutManager instanceof TestLayoutManager) {
452b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                TestLayoutManager lm = mLayoutManager;
453b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                // finish all layouts so that we get the correct exception
454b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                while (lm.layoutLatch.getCount() > 0) {
455b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                    lm.layoutLatch.countDown();
456b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                }
457b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            }
458b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        }
459b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar    }
460d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase}
461