blob: 0d8105d0e18a96e877163f08165ca41cb5d67666 [file] [log] [blame]
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.leanback.app;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import android.graphics.Rect;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.LargeTest;
import android.support.test.filters.SdkSuppress;
import android.support.test.runner.AndroidJUnit4;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.fragment.app.Fragment;
import androidx.leanback.test.R;
import androidx.leanback.testutils.PollingCheck;
import androidx.leanback.widget.ArrayObjectAdapter;
import androidx.leanback.widget.HeaderItem;
import androidx.leanback.widget.HorizontalGridView;
import androidx.leanback.widget.ItemBridgeAdapter;
import androidx.leanback.widget.ListRow;
import androidx.leanback.widget.ListRowPresenter;
import androidx.leanback.widget.ObjectAdapter;
import androidx.leanback.widget.OnItemViewClickedListener;
import androidx.leanback.widget.PageRow;
import androidx.leanback.widget.Presenter;
import androidx.leanback.widget.Row;
import androidx.leanback.widget.RowPresenter;
import androidx.leanback.widget.SinglePresenterSelector;
import androidx.leanback.widget.VerticalGridView;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
@LargeTest
@RunWith(AndroidJUnit4.class)
public class RowsSupportFragmentTest extends SingleSupportFragmentTestBase {
static final StringPresenter sCardPresenter = new StringPresenter();
static void loadData(ArrayObjectAdapter adapter, int numRows, int repeatPerRow) {
for (int i = 0; i < numRows; ++i) {
ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(sCardPresenter);
int index = 0;
for (int j = 0; j < repeatPerRow; ++j) {
listRowAdapter.add("Hello world-" + (index++));
listRowAdapter.add("This is a test-" + (index++));
listRowAdapter.add("Android TV-" + (index++));
listRowAdapter.add("Leanback-" + (index++));
listRowAdapter.add("Hello world-" + (index++));
listRowAdapter.add("Android TV-" + (index++));
listRowAdapter.add("Leanback-" + (index++));
listRowAdapter.add("GuidedStepSupportFragment-" + (index++));
}
HeaderItem header = new HeaderItem(i, "Row " + i);
adapter.add(new ListRow(header, listRowAdapter));
}
}
static Bundle saveActivityState(final SingleSupportFragmentTestActivity activity) {
final Bundle[] savedState = new Bundle[1];
// save activity state
InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
savedState[0] = activity.performSaveInstanceState();
}
});
return savedState[0];
}
static void waitForHeaderTransition(final F_Base fragment) {
// Wait header transition finishes
SystemClock.sleep(100);
PollingCheck.waitFor(new PollingCheck.PollingCheckCondition() {
@Override
public boolean canProceed() {
return !fragment.isInHeadersTransition();
}
});
}
static void selectAndWaitFragmentAnimation(final F_Base fragment, final int row,
final int item) {
InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
fragment.setSelectedPosition(row, true,
new ListRowPresenter.SelectItemViewHolderTask(item));
}
});
// Wait header transition finishes and scrolling stops
SystemClock.sleep(100);
PollingCheck.waitFor(new PollingCheck.PollingCheckCondition() {
@Override
public boolean canProceed() {
return !fragment.isInHeadersTransition()
&& !fragment.getHeadersSupportFragment().isScrolling();
}
});
}
public static class F_defaultAlignment extends RowsSupportFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ListRowPresenter lrp = new ListRowPresenter();
ArrayObjectAdapter adapter = new ArrayObjectAdapter(lrp);
setAdapter(adapter);
loadData(adapter, 10, 1);
}
}
@Test
public void defaultAlignment() throws Throwable {
SingleSupportFragmentTestActivity activity = launchAndWaitActivity(F_defaultAlignment.class, 1000);
final Rect rect = new Rect();
final VerticalGridView gridView = ((RowsSupportFragment) activity.getTestFragment())
.getVerticalGridView();
View row0 = gridView.findViewHolderForAdapterPosition(0).itemView;
rect.set(0, 0, row0.getWidth(), row0.getHeight());
gridView.offsetDescendantRectToMyCoords(row0, rect);
assertEquals("First row is initially aligned to top of screen", 0, rect.top);
sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
waitForScrollIdle(gridView);
View row1 = gridView.findViewHolderForAdapterPosition(1).itemView;
PollingCheck.waitFor(new PollingCheck.ViewStableOnScreen(row1));
rect.set(0, 0, row1.getWidth(), row1.getHeight());
gridView.offsetDescendantRectToMyCoords(row1, rect);
assertTrue("Second row should not be aligned to top of screen", rect.top > 0);
}
public static class F_selectBeforeSetAdapter extends RowsSupportFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setSelectedPosition(7, false);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
getVerticalGridView().requestLayout();
}
}, 100);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
ListRowPresenter lrp = new ListRowPresenter();
ArrayObjectAdapter adapter = new ArrayObjectAdapter(lrp);
setAdapter(adapter);
loadData(adapter, 10, 1);
}
}, 1000);
}
}
@Test
public void selectBeforeSetAdapter() throws InterruptedException {
SingleSupportFragmentTestActivity activity =
launchAndWaitActivity(F_selectBeforeSetAdapter.class, 2000);
final VerticalGridView gridView = ((RowsSupportFragment) activity.getTestFragment())
.getVerticalGridView();
assertEquals(7, gridView.getSelectedPosition());
assertNotNull(gridView.findViewHolderForAdapterPosition(7));
}
public static class F_selectBeforeAddData extends RowsSupportFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ListRowPresenter lrp = new ListRowPresenter();
final ArrayObjectAdapter adapter = new ArrayObjectAdapter(lrp);
setAdapter(adapter);
setSelectedPosition(7, false);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
getVerticalGridView().requestLayout();
}
}, 100);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
loadData(adapter, 10, 1);
}
}, 1000);
}
}
@Test
public void selectBeforeAddData() throws InterruptedException {
SingleSupportFragmentTestActivity activity =
launchAndWaitActivity(F_selectBeforeAddData.class, 2000);
final VerticalGridView gridView = ((RowsSupportFragment) activity.getTestFragment())
.getVerticalGridView();
assertEquals(7, gridView.getSelectedPosition());
assertNotNull(gridView.findViewHolderForAdapterPosition(7));
}
public static class F_selectAfterAddData extends RowsSupportFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ListRowPresenter lrp = new ListRowPresenter();
final ArrayObjectAdapter adapter = new ArrayObjectAdapter(lrp);
setAdapter(adapter);
loadData(adapter, 10, 1);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
setSelectedPosition(7, false);
}
}, 1000);
}
}
@Test
public void selectAfterAddData() throws InterruptedException {
SingleSupportFragmentTestActivity activity =
launchAndWaitActivity(F_selectAfterAddData.class, 2000);
final VerticalGridView gridView = ((RowsSupportFragment) activity.getTestFragment())
.getVerticalGridView();
assertEquals(7, gridView.getSelectedPosition());
assertNotNull(gridView.findViewHolderForAdapterPosition(7));
}
static WeakReference<F_restoreSelection> sLastF_restoreSelection;
public static class F_restoreSelection extends RowsSupportFragment {
public F_restoreSelection() {
sLastF_restoreSelection = new WeakReference<F_restoreSelection>(this);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ListRowPresenter lrp = new ListRowPresenter();
final ArrayObjectAdapter adapter = new ArrayObjectAdapter(lrp);
setAdapter(adapter);
loadData(adapter, 10, 1);
if (savedInstanceState == null) {
setSelectedPosition(7, false);
}
}
}
@Test
public void restoreSelection() {
final SingleSupportFragmentTestActivity activity =
launchAndWaitActivity(F_restoreSelection.class, 1000);
InstrumentationRegistry.getInstrumentation().runOnMainSync(
new Runnable() {
@Override
public void run() {
activity.recreate();
}
}
);
SystemClock.sleep(1000);
// mActivity is invalid after recreate(), a new Activity instance is created
// but we could get Fragment from static variable.
RowsSupportFragment fragment = sLastF_restoreSelection.get();
final VerticalGridView gridView = fragment.getVerticalGridView();
assertEquals(7, gridView.getSelectedPosition());
assertNotNull(gridView.findViewHolderForAdapterPosition(7));
}
public static class F_ListRowWithOnClick extends RowsSupportFragment {
Presenter.ViewHolder mLastClickedItemViewHolder;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setOnItemViewClickedListener(new OnItemViewClickedListener() {
@Override
public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item,
RowPresenter.ViewHolder rowViewHolder, Row row) {
mLastClickedItemViewHolder = itemViewHolder;
}
});
ListRowPresenter lrp = new ListRowPresenter();
ArrayObjectAdapter adapter = new ArrayObjectAdapter(lrp);
setAdapter(adapter);
loadData(adapter, 10, 1);
}
}
@Test
public void prefetchChildItemsBeforeAttach() throws Throwable {
SingleSupportFragmentTestActivity activity =
launchAndWaitActivity(F_ListRowWithOnClick.class, 1000);
F_ListRowWithOnClick fragment = (F_ListRowWithOnClick) activity.getTestFragment();
final VerticalGridView gridView = fragment.getVerticalGridView();
View lastRow = gridView.getChildAt(gridView.getChildCount() - 1);
final int lastRowPos = gridView.getChildAdapterPosition(lastRow);
InstrumentationRegistry.getInstrumentation().runOnMainSync(
new Runnable() {
public void run() {
gridView.setSelectedPositionSmooth(lastRowPos);
}
}
);
waitForScrollIdle(gridView);
ItemBridgeAdapter.ViewHolder prefetchedBridgeVh = (ItemBridgeAdapter.ViewHolder)
gridView.findViewHolderForAdapterPosition(lastRowPos + 1);
RowPresenter prefetchedRowPresenter = (RowPresenter) prefetchedBridgeVh.getPresenter();
final ListRowPresenter.ViewHolder prefetchedListRowVh = (ListRowPresenter.ViewHolder)
prefetchedRowPresenter.getRowViewHolder(prefetchedBridgeVh.getViewHolder());
fragment.mLastClickedItemViewHolder = null;
InstrumentationRegistry.getInstrumentation().runOnMainSync(
new Runnable() {
public void run() {
prefetchedListRowVh.getItemViewHolder(0).view.performClick();
}
}
);
assertSame(prefetchedListRowVh.getItemViewHolder(0), fragment.mLastClickedItemViewHolder);
}
@Test
public void changeHasStableIdToTrueAfterViewCreated() throws InterruptedException {
SingleSupportFragmentTestActivity activity =
launchAndWaitActivity(RowsSupportFragment.class, 2000);
final RowsSupportFragment fragment = (RowsSupportFragment) activity.getTestFragment();
InstrumentationRegistry.getInstrumentation().runOnMainSync(
new Runnable() {
public void run() {
ObjectAdapter adapter = new ObjectAdapter() {
@Override
public int size() {
return 0;
}
@Override
public Object get(int position) {
return null;
}
@Override
public long getId(int position) {
return 1;
}
};
adapter.setHasStableIds(true);
fragment.setAdapter(adapter);
}
}
);
}
static class StableIdAdapter extends ObjectAdapter {
ArrayList<Integer> mList = new ArrayList();
@Override
public long getId(int position) {
return mList.get(position).longValue();
}
@Override
public Object get(int position) {
return mList.get(position);
}
@Override
public int size() {
return mList.size();
}
}
public static class F_rowNotifyItemRangeChange extends BrowseSupportFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ListRowPresenter lrp = new ListRowPresenter();
final ArrayObjectAdapter adapter = new ArrayObjectAdapter(lrp);
for (int i = 0; i < 2; i++) {
StableIdAdapter listRowAdapter = new StableIdAdapter();
listRowAdapter.setHasStableIds(true);
listRowAdapter.setPresenterSelector(
new SinglePresenterSelector(sCardPresenter));
int index = 0;
listRowAdapter.mList.add(index++);
listRowAdapter.mList.add(index++);
listRowAdapter.mList.add(index++);
HeaderItem header = new HeaderItem(i, "Row " + i);
adapter.add(new ListRow(header, listRowAdapter));
}
setAdapter(adapter);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
StableIdAdapter rowAdapter = (StableIdAdapter)
((ListRow) adapter.get(1)).getAdapter();
rowAdapter.notifyItemRangeChanged(0, 3);
}
}, 500);
}
}
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.LOLLIPOP)
@Test
public void rowNotifyItemRangeChange() throws InterruptedException {
SingleSupportFragmentTestActivity activity = launchAndWaitActivity(
RowsSupportFragmentTest.F_rowNotifyItemRangeChange.class, 2000);
VerticalGridView verticalGridView = ((BrowseSupportFragment) activity.getTestFragment())
.getRowsSupportFragment().getVerticalGridView();
for (int i = 0; i < verticalGridView.getChildCount(); i++) {
HorizontalGridView horizontalGridView = verticalGridView.getChildAt(i)
.findViewById(R.id.row_content);
for (int j = 0; j < horizontalGridView.getChildCount(); j++) {
assertEquals(horizontalGridView.getPaddingTop(),
horizontalGridView.getChildAt(j).getTop());
}
}
}
public static class F_rowNotifyItemRangeChangeWithTransition extends BrowseSupportFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ListRowPresenter lrp = new ListRowPresenter();
prepareEntranceTransition();
final ArrayObjectAdapter adapter = new ArrayObjectAdapter(lrp);
for (int i = 0; i < 2; i++) {
StableIdAdapter listRowAdapter = new StableIdAdapter();
listRowAdapter.setHasStableIds(true);
listRowAdapter.setPresenterSelector(
new SinglePresenterSelector(sCardPresenter));
int index = 0;
listRowAdapter.mList.add(index++);
listRowAdapter.mList.add(index++);
listRowAdapter.mList.add(index++);
HeaderItem header = new HeaderItem(i, "Row " + i);
adapter.add(new ListRow(header, listRowAdapter));
}
setAdapter(adapter);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
StableIdAdapter rowAdapter = (StableIdAdapter)
((ListRow) adapter.get(1)).getAdapter();
rowAdapter.notifyItemRangeChanged(0, 3);
}
}, 500);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
startEntranceTransition();
}
}, 520);
}
}
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.LOLLIPOP)
@Test
public void rowNotifyItemRangeChangeWithTransition() throws InterruptedException {
SingleSupportFragmentTestActivity activity = launchAndWaitActivity(
RowsSupportFragmentTest.F_rowNotifyItemRangeChangeWithTransition.class, 3000);
VerticalGridView verticalGridView = ((BrowseSupportFragment) activity.getTestFragment())
.getRowsSupportFragment().getVerticalGridView();
for (int i = 0; i < verticalGridView.getChildCount(); i++) {
HorizontalGridView horizontalGridView = verticalGridView.getChildAt(i)
.findViewById(R.id.row_content);
for (int j = 0; j < horizontalGridView.getChildCount(); j++) {
assertEquals(horizontalGridView.getPaddingTop(),
horizontalGridView.getChildAt(j).getTop());
assertEquals(0, horizontalGridView.getChildAt(j).getTranslationY(), 0.1f);
}
}
}
public static class F_Base extends BrowseSupportFragment {
List<Long> mEntranceTransitionStartTS = new ArrayList();
List<Long> mEntranceTransitionEndTS = new ArrayList();
@Override
protected void onEntranceTransitionStart() {
super.onEntranceTransitionStart();
mEntranceTransitionStartTS.add(SystemClock.uptimeMillis());
}
@Override
protected void onEntranceTransitionEnd() {
super.onEntranceTransitionEnd();
mEntranceTransitionEndTS.add(SystemClock.uptimeMillis());
}
public void assertExecutedEntranceTransition() {
assertEquals(1, mEntranceTransitionStartTS.size());
assertEquals(1, mEntranceTransitionEndTS.size());
assertTrue(mEntranceTransitionEndTS.get(0) - mEntranceTransitionStartTS.get(0) > 100);
}
public void assertNoEntranceTransition() {
assertEquals(0, mEntranceTransitionStartTS.size());
assertEquals(0, mEntranceTransitionEndTS.size());
}
/**
* Util to wait PageFragment swapped.
*/
Fragment waitPageFragment(final Class pageFragmentClass) {
PollingCheck.waitFor(new PollingCheck.PollingCheckCondition() {
@Override
public boolean canProceed() {
return pageFragmentClass.isInstance(getMainFragment())
&& getMainFragment().getView() != null;
}
});
return getMainFragment();
}
/**
* Wait until a fragment for non-page Row is created. Does not apply to the case a
* RowsSupportFragment is created on a PageRow.
*/
RowsSupportFragment waitRowsSupportFragment() {
PollingCheck.waitFor(new PollingCheck.PollingCheckCondition() {
@Override
public boolean canProceed() {
return mMainFragmentListRowDataAdapter != null
&& getMainFragment() instanceof RowsSupportFragment
&& !(getMainFragment() instanceof SampleRowsSupportFragment);
}
});
return (RowsSupportFragment) getMainFragment();
}
}
static ObjectAdapter createListRowAdapter() {
StableIdAdapter listRowAdapter = new StableIdAdapter();
listRowAdapter.setHasStableIds(false);
listRowAdapter.setPresenterSelector(
new SinglePresenterSelector(sCardPresenter));
int index = 0;
listRowAdapter.mList.add(index++);
listRowAdapter.mList.add(index++);
listRowAdapter.mList.add(index++);
return listRowAdapter;
}
/**
* Create BrowseSupportFragmentAdapter with 3 ListRows
*/
static ArrayObjectAdapter createListRowsAdapter() {
ListRowPresenter lrp = new ListRowPresenter();
final ArrayObjectAdapter adapter = new ArrayObjectAdapter(lrp);
for (int i = 0; i < 3; i++) {
ObjectAdapter listRowAdapter = createListRowAdapter();
HeaderItem header = new HeaderItem(i, "Row " + i);
adapter.add(new ListRow(header, listRowAdapter));
}
return adapter;
}
/**
* A typical BrowseSupportFragment with multiple rows that start entrance transition
*/
public static class F_standard extends F_Base {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null) {
prepareEntranceTransition();
}
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
setAdapter(createListRowsAdapter());
startEntranceTransition();
}
}, 100);
}
}
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.LOLLIPOP)
@Test
public void browseFragmentSetNullAdapter() throws InterruptedException {
final SingleSupportFragmentTestActivity activity = launchAndWaitActivity(
RowsSupportFragmentTest.F_standard.class, 2000);
final F_standard fragment = ((F_standard) activity.getTestFragment());
fragment.assertExecutedEntranceTransition();
final ObjectAdapter adapter1 = fragment.getAdapter();
ListRowDataAdapter wrappedAdapter = fragment.mMainFragmentListRowDataAdapter;
assertTrue(adapter1.hasObserver());
assertTrue(wrappedAdapter.hasObserver());
InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
fragment.setAdapter(null);
}
});
// adapter should no longer has observer and there is no reference to adapter from
// BrowseSupportFragment.
assertFalse(adapter1.hasObserver());
assertFalse(wrappedAdapter.hasObserver());
assertNull(fragment.getAdapter());
assertNull(fragment.mMainFragmentListRowDataAdapter);
// RowsSupportFragment is still there
assertTrue(fragment.mMainFragment instanceof RowsSupportFragment);
assertNotNull(fragment.mMainFragmentRowsAdapter);
assertNotNull(fragment.mMainFragmentAdapter);
// initialize to same adapter
InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
fragment.setAdapter(adapter1);
}
});
assertTrue(adapter1.hasObserver());
assertNotSame(wrappedAdapter, fragment.mMainFragmentListRowDataAdapter);
}
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.LOLLIPOP)
@Test
public void browseFragmentChangeAdapter() throws InterruptedException {
final SingleSupportFragmentTestActivity activity = launchAndWaitActivity(
RowsSupportFragmentTest.F_standard.class, 2000);
final F_standard fragment = ((F_standard) activity.getTestFragment());
fragment.assertExecutedEntranceTransition();
final ObjectAdapter adapter1 = fragment.getAdapter();
ListRowDataAdapter wrappedAdapter = fragment.mMainFragmentListRowDataAdapter;
assertTrue(adapter1.hasObserver());
assertTrue(wrappedAdapter.hasObserver());
final ObjectAdapter adapter2 = createListRowsAdapter();
InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
fragment.setAdapter(adapter2);
}
});
// adapter1 should no longer has observer and adapter2 will have observer
assertFalse(adapter1.hasObserver());
assertFalse(wrappedAdapter.hasObserver());
assertSame(adapter2, fragment.getAdapter());
assertNotSame(wrappedAdapter, fragment.mMainFragmentListRowDataAdapter);
assertTrue(adapter2.hasObserver());
assertTrue(fragment.mMainFragmentListRowDataAdapter.hasObserver());
}
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.LOLLIPOP)
@Test
public void browseFragmentChangeAdapterToPage() throws InterruptedException {
final SingleSupportFragmentTestActivity activity = launchAndWaitActivity(
RowsSupportFragmentTest.F_standard.class, 2000);
final F_standard fragment = ((F_standard) activity.getTestFragment());
fragment.assertExecutedEntranceTransition();
final ObjectAdapter adapter1 = fragment.getAdapter();
ListRowDataAdapter wrappedAdapter = fragment.mMainFragmentListRowDataAdapter;
assertTrue(adapter1.hasObserver());
assertTrue(wrappedAdapter.hasObserver());
final ObjectAdapter adapter2 = create2PageRow3ListRow();
fragment.getMainFragmentRegistry().registerFragment(MyPageRow.class,
new MyFragmentFactory());
InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
fragment.setAdapter(adapter2);
}
});
fragment.waitPageFragment(SampleRowsSupportFragment.class);
// adapter1 should no longer has observer and adapter2 will have observer
assertFalse(adapter1.hasObserver());
assertFalse(wrappedAdapter.hasObserver());
assertSame(adapter2, fragment.getAdapter());
assertNull(fragment.mMainFragmentListRowDataAdapter);
assertTrue(adapter2.hasObserver());
}
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.LOLLIPOP)
@Test
public void browseFragmentNotifyDataChangeListRowToPage() throws InterruptedException {
final SingleSupportFragmentTestActivity activity = launchAndWaitActivity(
RowsSupportFragmentTest.F_standard.class, 2000);
final F_standard fragment = ((F_standard) activity.getTestFragment());
fragment.assertExecutedEntranceTransition();
final ArrayObjectAdapter adapter1 = (ArrayObjectAdapter) fragment.getAdapter();
ListRowDataAdapter wrappedAdapter = fragment.mMainFragmentListRowDataAdapter;
assertTrue(adapter1.hasObserver());
assertTrue(wrappedAdapter.hasObserver());
fragment.getMainFragmentRegistry().registerFragment(MyPageRow.class,
new MyFragmentFactory());
InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
adapter1.removeItems(0, 1);
adapter1.add(0, new MyPageRow(0));
}
});
fragment.waitPageFragment(SampleRowsSupportFragment.class);
assertTrue(adapter1.hasObserver());
assertNull(fragment.mMainFragmentListRowDataAdapter);
}
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.LOLLIPOP)
@Test
public void browseFragmentNotifyItemChangeListRowToPage() throws InterruptedException {
final SingleSupportFragmentTestActivity activity = launchAndWaitActivity(
RowsSupportFragmentTest.F_standard.class, 2000);
final F_standard fragment = ((F_standard) activity.getTestFragment());
fragment.assertExecutedEntranceTransition();
final ArrayObjectAdapter adapter1 = (ArrayObjectAdapter) fragment.getAdapter();
ListRowDataAdapter wrappedAdapter = fragment.mMainFragmentListRowDataAdapter;
assertTrue(adapter1.hasObserver());
assertTrue(wrappedAdapter.hasObserver());
fragment.getMainFragmentRegistry().registerFragment(MyPageRow.class,
new MyFragmentFactory());
InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
adapter1.replace(0, new MyPageRow(0));
}
});
fragment.waitPageFragment(SampleRowsSupportFragment.class);
assertTrue(adapter1.hasObserver());
assertNull(fragment.mMainFragmentListRowDataAdapter);
}
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.LOLLIPOP)
@Test
public void browseFragmentNotifyDataChangeListRowToListRow() throws InterruptedException {
final SingleSupportFragmentTestActivity activity = launchAndWaitActivity(
RowsSupportFragmentTest.F_standard.class, 2000);
final F_standard fragment = ((F_standard) activity.getTestFragment());
fragment.assertExecutedEntranceTransition();
final ArrayObjectAdapter adapter1 = (ArrayObjectAdapter) fragment.getAdapter();
ListRowDataAdapter wrappedAdapter = fragment.mMainFragmentListRowDataAdapter;
assertTrue(adapter1.hasObserver());
assertTrue(wrappedAdapter.hasObserver());
fragment.getMainFragmentRegistry().registerFragment(MyPageRow.class,
new MyFragmentFactory());
InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
ObjectAdapter listRowAdapter = createListRowAdapter();
HeaderItem header = new HeaderItem(0, "Row 0 changed");
adapter1.removeItems(0, 1);
adapter1.add(0, new ListRow(header, listRowAdapter));
}
});
assertTrue(adapter1.hasObserver());
assertTrue(wrappedAdapter.hasObserver());
assertSame(wrappedAdapter, fragment.mMainFragmentListRowDataAdapter);
}
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.LOLLIPOP)
@Test
public void browseFragmentNotifyItemChangeListRowToListRow() throws InterruptedException {
final SingleSupportFragmentTestActivity activity = launchAndWaitActivity(
RowsSupportFragmentTest.F_standard.class, 2000);
final F_standard fragment = ((F_standard) activity.getTestFragment());
fragment.assertExecutedEntranceTransition();
final ArrayObjectAdapter adapter1 = (ArrayObjectAdapter) fragment.getAdapter();
ListRowDataAdapter wrappedAdapter = fragment.mMainFragmentListRowDataAdapter;
assertTrue(adapter1.hasObserver());
assertTrue(wrappedAdapter.hasObserver());
fragment.getMainFragmentRegistry().registerFragment(MyPageRow.class,
new MyFragmentFactory());
InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
ObjectAdapter listRowAdapter = createListRowAdapter();
HeaderItem header = new HeaderItem(0, "Row 0 changed");
adapter1.replace(0, new ListRow(header, listRowAdapter));
}
});
assertTrue(adapter1.hasObserver());
assertTrue(wrappedAdapter.hasObserver());
assertSame(wrappedAdapter, fragment.mMainFragmentListRowDataAdapter);
}
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.LOLLIPOP)
@Test
public void browseFragmentChangeAdapterPageToPage() throws InterruptedException {
final SingleSupportFragmentTestActivity activity = launchAndWaitActivity(
RowsSupportFragmentTest.F_2PageRow3ListRow.class, 2000);
final F_2PageRow3ListRow fragment = ((F_2PageRow3ListRow) activity.getTestFragment());
fragment.assertExecutedEntranceTransition();
final ObjectAdapter adapter1 = fragment.getAdapter();
assertNull(fragment.mMainFragmentListRowDataAdapter);
assertTrue(adapter1.hasObserver());
final ObjectAdapter adapter2 = create2PageRow3ListRow();
InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
fragment.setAdapter(adapter2);
}
});
fragment.waitPageFragment(SampleRowsSupportFragment.class);
// adapter1 should no longer has observer and adapter2 will have observer
assertFalse(adapter1.hasObserver());
assertSame(adapter2, fragment.getAdapter());
assertNull(fragment.mMainFragmentListRowDataAdapter);
assertTrue(adapter2.hasObserver());
}
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.LOLLIPOP)
@Test
public void browseFragmentNotifyChangePageToPage() throws InterruptedException {
final SingleSupportFragmentTestActivity activity = launchAndWaitActivity(
RowsSupportFragmentTest.F_2PageRow3ListRow.class, 2000);
final F_2PageRow3ListRow fragment = ((F_2PageRow3ListRow) activity.getTestFragment());
fragment.assertExecutedEntranceTransition();
final ArrayObjectAdapter adapter1 = (ArrayObjectAdapter) fragment.getAdapter();
assertNull(fragment.mMainFragmentListRowDataAdapter);
assertTrue(adapter1.hasObserver());
InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
adapter1.removeItems(0, 1);
adapter1.add(0, new MyPageRow(1));
}
});
fragment.waitPageFragment(SampleFragment.class);
// adapter1 should no longer has observer and adapter2 will have observer
assertTrue(adapter1.hasObserver());
assertNull(fragment.mMainFragmentListRowDataAdapter);
}
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.LOLLIPOP)
@Test
public void browseFragmentNotifyItemChangePageToPage() throws InterruptedException {
final SingleSupportFragmentTestActivity activity = launchAndWaitActivity(
RowsSupportFragmentTest.F_2PageRow3ListRow.class, 2000);
final F_2PageRow3ListRow fragment = ((F_2PageRow3ListRow) activity.getTestFragment());
fragment.assertExecutedEntranceTransition();
final ArrayObjectAdapter adapter1 = (ArrayObjectAdapter) fragment.getAdapter();
assertNull(fragment.mMainFragmentListRowDataAdapter);
assertTrue(adapter1.hasObserver());
InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
adapter1.replace(0, new MyPageRow(1));
}
});
fragment.waitPageFragment(SampleFragment.class);
// adapter1 should no longer has observer and adapter2 will have observer
assertTrue(adapter1.hasObserver());
assertNull(fragment.mMainFragmentListRowDataAdapter);
}
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.LOLLIPOP)
@Test
public void browseFragmentChangeAdapterPageToListRow() throws InterruptedException {
final SingleSupportFragmentTestActivity activity = launchAndWaitActivity(
RowsSupportFragmentTest.F_2PageRow3ListRow.class, 2000);
final F_2PageRow3ListRow fragment = ((F_2PageRow3ListRow) activity.getTestFragment());
fragment.assertExecutedEntranceTransition();
final ObjectAdapter adapter1 = fragment.getAdapter();
assertNull(fragment.mMainFragmentListRowDataAdapter);
assertTrue(adapter1.hasObserver());
final ObjectAdapter adapter2 = createListRowsAdapter();
InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
fragment.setAdapter(adapter2);
}
});
fragment.waitRowsSupportFragment();
// adapter1 should no longer has observer and adapter2 will have observer
assertFalse(adapter1.hasObserver());
assertSame(adapter2, fragment.getAdapter());
assertTrue(adapter2.hasObserver());
assertTrue(fragment.mMainFragmentListRowDataAdapter.hasObserver());
}
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.LOLLIPOP)
@Test
public void browseFragmentNotifyDataChangePageToListRow() throws InterruptedException {
final SingleSupportFragmentTestActivity activity = launchAndWaitActivity(
RowsSupportFragmentTest.F_2PageRow3ListRow.class, 2000);
final F_2PageRow3ListRow fragment = ((F_2PageRow3ListRow) activity.getTestFragment());
fragment.assertExecutedEntranceTransition();
final ArrayObjectAdapter adapter1 = (ArrayObjectAdapter) fragment.getAdapter();
assertNull(fragment.mMainFragmentListRowDataAdapter);
assertTrue(adapter1.hasObserver());
InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
ObjectAdapter listRowAdapter = createListRowAdapter();
HeaderItem header = new HeaderItem(0, "Row 0 changed");
adapter1.removeItems(0, 1);
adapter1.add(0, new ListRow(header, listRowAdapter));
}
});
fragment.waitRowsSupportFragment();
assertTrue(adapter1.hasObserver());
assertTrue(fragment.mMainFragmentListRowDataAdapter.hasObserver());
}
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.LOLLIPOP)
@Test
public void browseFragmentNotifyItemChangePageToListRow() throws InterruptedException {
final SingleSupportFragmentTestActivity activity = launchAndWaitActivity(
RowsSupportFragmentTest.F_2PageRow3ListRow.class, 2000);
final F_2PageRow3ListRow fragment = ((F_2PageRow3ListRow) activity.getTestFragment());
fragment.assertExecutedEntranceTransition();
final ArrayObjectAdapter adapter1 = (ArrayObjectAdapter) fragment.getAdapter();
assertNull(fragment.mMainFragmentListRowDataAdapter);
assertTrue(adapter1.hasObserver());
InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
ObjectAdapter listRowAdapter = createListRowAdapter();
HeaderItem header = new HeaderItem(0, "Row 0 changed");
adapter1.replace(0, new ListRow(header, listRowAdapter));
}
});
fragment.waitRowsSupportFragment();
assertTrue(adapter1.hasObserver());
assertTrue(fragment.mMainFragmentListRowDataAdapter.hasObserver());
}
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.LOLLIPOP)
@Test
public void browseFragmentRestore() throws InterruptedException {
final SingleSupportFragmentTestActivity activity = launchAndWaitActivity(
RowsSupportFragmentTest.F_standard.class, 2000);
final F_standard fragment = ((F_standard) activity.getTestFragment());
fragment.assertExecutedEntranceTransition();
// select item 2 on row 1
selectAndWaitFragmentAnimation(fragment, 1, 2);
// save activity to state
Bundle savedState = saveActivityState(activity);
activity.finish();
// recreate activity with saved state
SingleSupportFragmentTestActivity activity2 = launchAndWaitActivity(
RowsSupportFragmentTest.F_standard.class,
new Options().savedInstance(savedState), 2000);
final F_standard fragment2 = ((F_standard) activity2.getTestFragment());
// validate restored activity selected row and selected item
fragment2.assertNoEntranceTransition();
assertEquals(1, fragment2.getSelectedPosition());
assertEquals(2, ((ListRowPresenter.ViewHolder) fragment2.getSelectedRowViewHolder())
.getSelectedPosition());
activity2.finish();
}
public static class MyPageRow extends PageRow {
public int type;
public MyPageRow(int type) {
super(new HeaderItem(100 + type, "page type " + type));
this.type = type;
}
}
/**
* A RowsSupportFragment that is a separate page in BrowseSupportFragment.
*/
public static class SampleRowsSupportFragment extends RowsSupportFragment {
public SampleRowsSupportFragment() {
// simulates late data loading:
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
setAdapter(createListRowsAdapter());
if (getMainFragmentAdapter() != null) {
getMainFragmentAdapter().getFragmentHost()
.notifyDataReady(getMainFragmentAdapter());
}
}
}, 500);
}
}
/**
* A custom Fragment that is a separate page in BrowseSupportFragment.
*/
public static class SampleFragment extends Fragment implements
BrowseSupportFragment.MainFragmentAdapterProvider {
public static class PageFragmentAdapterImpl extends
BrowseSupportFragment.MainFragmentAdapter<SampleFragment> {
public PageFragmentAdapterImpl(SampleFragment fragment) {
super(fragment);
setScalingEnabled(true);
}
@Override
public void setEntranceTransitionState(boolean state) {
getFragment().setEntranceTransitionState(state);
}
}
final PageFragmentAdapterImpl mMainFragmentAdapter = new PageFragmentAdapterImpl(this);
void setEntranceTransitionState(boolean state) {
final View view = getView();
int visibility = state ? View.VISIBLE : View.INVISIBLE;
view.findViewById(R.id.tv1).setVisibility(visibility);
view.findViewById(R.id.tv2).setVisibility(visibility);
view.findViewById(R.id.tv3).setVisibility(visibility);
}
@Override
public View onCreateView(
final LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.page_fragment, container, false);
return view;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
// static layout has view and data ready immediately
mMainFragmentAdapter.getFragmentHost().notifyViewCreated(mMainFragmentAdapter);
mMainFragmentAdapter.getFragmentHost().notifyDataReady(mMainFragmentAdapter);
}
@Override
public BrowseSupportFragment.MainFragmentAdapter getMainFragmentAdapter() {
return mMainFragmentAdapter;
}
}
/**
* Create BrowseSupportFragmentAdapter with 3 ListRows and 2 PageRows
*/
private static ArrayObjectAdapter create3ListRow2PageRowAdapter() {
ListRowPresenter lrp = new ListRowPresenter();
final ArrayObjectAdapter adapter = new ArrayObjectAdapter(lrp);
for (int i = 0; i < 3; i++) {
StableIdAdapter listRowAdapter = new StableIdAdapter();
listRowAdapter.setHasStableIds(false);
listRowAdapter.setPresenterSelector(
new SinglePresenterSelector(sCardPresenter));
int index = 0;
listRowAdapter.mList.add(index++);
listRowAdapter.mList.add(index++);
listRowAdapter.mList.add(index++);
HeaderItem header = new HeaderItem(i, "Row " + i);
adapter.add(new ListRow(header, listRowAdapter));
}
adapter.add(new MyPageRow(0));
adapter.add(new MyPageRow(1));
return adapter;
}
/**
* Create BrowseSupportFragmentAdapter with 2 PageRows then 3 ListRow
*/
private static ArrayObjectAdapter create2PageRow3ListRow() {
ListRowPresenter lrp = new ListRowPresenter();
final ArrayObjectAdapter adapter = new ArrayObjectAdapter(lrp);
adapter.add(new MyPageRow(0));
adapter.add(new MyPageRow(1));
for (int i = 0; i < 3; i++) {
StableIdAdapter listRowAdapter = new StableIdAdapter();
listRowAdapter.setHasStableIds(false);
listRowAdapter.setPresenterSelector(
new SinglePresenterSelector(sCardPresenter));
int index = 0;
listRowAdapter.mList.add(index++);
listRowAdapter.mList.add(index++);
listRowAdapter.mList.add(index++);
HeaderItem header = new HeaderItem(i, "Row " + i);
adapter.add(new ListRow(header, listRowAdapter));
}
return adapter;
}
static class MyFragmentFactory extends BrowseSupportFragment.FragmentFactory {
@Override
public Fragment createFragment(Object rowObj) {
MyPageRow row = (MyPageRow) rowObj;
if (row.type == 0) {
return new SampleRowsSupportFragment();
} else if (row.type == 1) {
return new SampleFragment();
}
return null;
}
}
/**
* A BrowseSupportFragment with three ListRows, one SampleRowsSupportFragment and one SampleFragment.
*/
public static class F_3ListRow2PageRow extends F_Base {
public F_3ListRow2PageRow() {
getMainFragmentRegistry().registerFragment(MyPageRow.class, new MyFragmentFactory());
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null) {
prepareEntranceTransition();
}
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
setAdapter(create3ListRow2PageRowAdapter());
startEntranceTransition();
}
}, 100);
}
}
/**
* A BrowseSupportFragment with three ListRows, one SampleRowsSupportFragment and one SampleFragment.
*/
public static class F_2PageRow3ListRow extends F_Base {
public F_2PageRow3ListRow() {
getMainFragmentRegistry().registerFragment(MyPageRow.class, new MyFragmentFactory());
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null) {
prepareEntranceTransition();
}
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
setAdapter(create2PageRow3ListRow());
startEntranceTransition();
}
}, 100);
}
}
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.LOLLIPOP)
@Test
public void mixedBrowseSupportFragmentRestoreToListRow() throws Throwable {
final SingleSupportFragmentTestActivity activity = launchAndWaitActivity(
RowsSupportFragmentTest.F_3ListRow2PageRow.class, 2000);
final F_3ListRow2PageRow fragment = ((F_3ListRow2PageRow) activity.getTestFragment());
fragment.assertExecutedEntranceTransition();
// select item 2 on row 1.
selectAndWaitFragmentAnimation(fragment, 1, 2);
Bundle savedState = saveActivityState(activity);
activity.finish();
// start a new activity with the state
SingleSupportFragmentTestActivity activity2 = launchAndWaitActivity(
RowsSupportFragmentTest.F_standard.class,
new Options().savedInstance(savedState), 2000);
final F_3ListRow2PageRow fragment2 = ((F_3ListRow2PageRow) activity2.getTestFragment());
assertFalse(fragment2.isShowingHeaders());
fragment2.assertNoEntranceTransition();
assertEquals(1, fragment2.getSelectedPosition());
assertEquals(2, ((ListRowPresenter.ViewHolder) fragment2.getSelectedRowViewHolder())
.getSelectedPosition());
activity2.finish();
}
void mixedBrowseSupportFragmentRestoreToSampleRowsSupportFragment(final boolean hideFastLane)
throws Throwable {
final SingleSupportFragmentTestActivity activity = launchAndWaitActivity(
RowsSupportFragmentTest.F_3ListRow2PageRow.class, 2000);
final F_3ListRow2PageRow fragment = ((F_3ListRow2PageRow) activity.getTestFragment());
fragment.assertExecutedEntranceTransition();
// select row 3 which is mapped to SampleRowsSupportFragment.
InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
fragment.setSelectedPosition(3, true);
}
});
// Wait SampleRowsSupportFragment being created
final SampleRowsSupportFragment mainFragment = (SampleRowsSupportFragment) fragment.waitPageFragment(
SampleRowsSupportFragment.class);
InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
if (hideFastLane) {
fragment.startHeadersTransition(false);
}
}
});
// Wait header transition finishes
waitForHeaderTransition(fragment);
// Select item 1 on row 1 in SampleRowsSupportFragment
InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
mainFragment.setSelectedPosition(1, true,
new ListRowPresenter.SelectItemViewHolderTask(1));
}
});
// Save activity state
Bundle savedState = saveActivityState(activity);
activity.finish();
SingleSupportFragmentTestActivity activity2 = launchAndWaitActivity(
RowsSupportFragmentTest.F_3ListRow2PageRow.class,
new Options().savedInstance(savedState), 2000);
final F_3ListRow2PageRow fragment2 = ((F_3ListRow2PageRow) activity2.getTestFragment());
final SampleRowsSupportFragment mainFragment2 = (SampleRowsSupportFragment) fragment2.waitPageFragment(
SampleRowsSupportFragment.class);
assertEquals(!hideFastLane, fragment2.isShowingHeaders());
fragment2.assertNoEntranceTransition();
// Validate BrowseSupportFragment selected row 3 (mapped to SampleRowsSupportFragment)
assertEquals(3, fragment2.getSelectedPosition());
// Validate SampleRowsSupportFragment's selected row and selected item
assertEquals(1, mainFragment2.getSelectedPosition());
assertEquals(1, ((ListRowPresenter.ViewHolder) mainFragment2
.findRowViewHolderByPosition(1)).getSelectedPosition());
activity2.finish();
}
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.LOLLIPOP)
@Test
public void mixedBrowseSupportFragmentRestoreToSampleRowsSupportFragmentHideFastLane() throws Throwable {
mixedBrowseSupportFragmentRestoreToSampleRowsSupportFragment(true);
}
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.LOLLIPOP)
@Test
public void mixedBrowseSupportFragmentRestoreToSampleRowsSupportFragmentShowFastLane() throws Throwable {
mixedBrowseSupportFragmentRestoreToSampleRowsSupportFragment(false);
}
void mixedBrowseSupportFragmentRestoreToSampleFragment(final boolean hideFastLane)
throws Throwable {
final SingleSupportFragmentTestActivity activity = launchAndWaitActivity(
RowsSupportFragmentTest.F_3ListRow2PageRow.class, 2000);
final F_3ListRow2PageRow fragment = ((F_3ListRow2PageRow) activity.getTestFragment());
fragment.assertExecutedEntranceTransition();
// select row 3 which is mapped to SampleFragment.
InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
fragment.setSelectedPosition(4, true);
}
});
// Wait SampleFragment to be created
final SampleFragment mainFragment = (SampleFragment) fragment.waitPageFragment(
SampleFragment.class);
InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
if (hideFastLane) {
fragment.startHeadersTransition(false);
}
}
});
waitForHeaderTransition(fragment);
InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
// change TextView content which should be saved in states.
TextView t = mainFragment.getView().findViewById(R.id.tv2);
t.setText("changed text");
}
});
// Save activity state
Bundle savedState = saveActivityState(activity);
activity.finish();
SingleSupportFragmentTestActivity activity2 = launchAndWaitActivity(
RowsSupportFragmentTest.F_3ListRow2PageRow.class,
new Options().savedInstance(savedState), 2000);
final F_3ListRow2PageRow fragment2 = ((F_3ListRow2PageRow) activity2.getTestFragment());
final SampleFragment mainFragment2 = (SampleFragment) fragment2.waitPageFragment(
SampleFragment.class);
assertEquals(!hideFastLane, fragment2.isShowingHeaders());
fragment2.assertNoEntranceTransition();
// Validate BrowseSupportFragment selected row 3 (mapped to SampleFragment)
assertEquals(4, fragment2.getSelectedPosition());
// Validate SampleFragment's view states are restored
TextView t = mainFragment2.getView().findViewById(R.id.tv2);
assertEquals("changed text", t.getText().toString());
activity2.finish();
}
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.LOLLIPOP)
@Test
public void mixedBrowseSupportFragmentRestoreToSampleFragmentHideFastLane() throws Throwable {
mixedBrowseSupportFragmentRestoreToSampleFragment(true);
}
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.LOLLIPOP)
@Test
public void mixedBrowseSupportFragmentRestoreToSampleFragmentShowFastLane() throws Throwable {
mixedBrowseSupportFragmentRestoreToSampleFragment(false);
}
}