@Nullable public static DebugComponent getRootInstance(LithoView view) { return getRootInstance(view.getComponentTree()); }
public static void mountLithoView(LithoView lithoView) { lithoView.getComponentTree().mountComponent(null, true); }
@Override public void bind(@NonNull LithoView view, @NonNull List<Object> payloads) { if (payloads.isEmpty()) { bind(view); } else { view.getComponentTree().setRoot(getComponent(view.getComponentContext())); } }
@Override public void bind(@NonNull LithoView view, @NonNull EpoxyModel<?> previouslyBoundModel) { view.getComponentTree().setRoot(getComponent(view.getComponentContext())); }
/** * Restore a previously saved root layout reference. * * @see #getRootLayoutRef(LithoView) */ @ThreadConfined(ThreadConfined.UI) public static void setRootLayoutRef(final LithoView view, final InternalNodeRef rootLayoutNode) { final ComponentTree componentTree = view.getComponentTree(); final LayoutState mainThreadLayoutState = componentTree != null ? componentTree.getMainThreadLayoutState() : null; if (mainThreadLayoutState != null) { mainThreadLayoutState.mLayoutRoot = rootLayoutNode.mInternalNodeRef; } } }
/** * Obtain a reference to a LithoView's internal layout root, if present. This is used to restore a * view's root after it has been freed for testing purposes. * * @see #setRootLayoutRef(LithoView, InternalNodeRef) */ @ThreadConfined(ThreadConfined.UI) @Nullable public static InternalNodeRef getRootLayoutRef(final LithoView view) { final ComponentTree componentTree = view.getComponentTree(); final LayoutState mainThreadLayoutState = componentTree != null ? componentTree.getMainThreadLayoutState() : null; return mainThreadLayoutState != null ? new InternalNodeRef(mainThreadLayoutState.getLayoutRoot()) : null; }
@Test public void testChildViewGroupIncrementallyMounted() { final ViewGroup mountedView = mock(ViewGroup.class); when(mountedView.getChildCount()).thenReturn(3); final LithoView childView1 = getMockLithoViewWithBounds(new Rect(5, 10, 20, 30)); when(mountedView.getChildAt(0)).thenReturn(childView1); final LithoView childView2 = getMockLithoViewWithBounds(new Rect(10, 10, 50, 60)); when(mountedView.getChildAt(1)).thenReturn(childView2); final LithoView childView3 = getMockLithoViewWithBounds(new Rect(30, 35, 50, 60)); when(mountedView.getChildAt(2)).thenReturn(childView3); final LithoView lithoView = ComponentTestHelper.mountComponent( TestViewComponent.create(mContext).testView(mountedView)); lithoView.getComponentTree().mountComponent(new Rect(15, 15, 40, 40), true); verify(childView1).performIncrementalMount(); verify(childView2).performIncrementalMount(); verify(childView3).performIncrementalMount(); }
void mount(Component component, int width, int height) { if (mLithoView.getComponentTree() == null) { mLithoView.setComponentTree( ComponentTree.create(mLithoView.getComponentContext(), component) .incrementalMount(false) .build()); } else { mLithoView.setComponent(component); } mComponentWidth = width; mComponentHeight = height; }
@Override public void bind(@NonNull LithoView view) { Component<T> component = getComponent(view.getComponentContext()); if (view.getComponentTree() == null) { view.setComponentTree(ComponentTree.create(view.getComponentContext(), component) .asyncStateUpdates(false) // does this need to be off? .layoutThreadLooper(Looper.getMainLooper()) .incrementalMount( false) // this needs to be off for recyclerview to work. Should we manually // incrementally mount views in a scroll listener? .layoutDiffing(false) // should we use this? .build()); } view.setComponent(component); }
@Test public void testMeasureComputesLayoutStateWhenSpecsAreNotExact() { mLithoView = new LithoView(RuntimeEnvironment.application); mLithoView.setComponent( TestDrawableComponent.create(mLithoView.getComponentContext()).heightPx(100).build()); mLithoView.measure(makeMeasureSpec(100, EXACTLY), makeMeasureSpec(100, AT_MOST)); assertThat(mLithoView.getMeasuredWidth()).isEqualTo(100); assertThat(mLithoView.getMeasuredHeight()).isEqualTo(100); assertThat(mLithoView.getComponentTree().getMainThreadLayoutState()).isNotNull(); }
@Test public void testMeasureDoesNotComputeLayoutStateWhenSpecsAreExact() { mLithoView = new LithoView(RuntimeEnvironment.application); mLithoView.setComponent(TestDrawableComponent.create(mLithoView.getComponentContext()).build()); mLithoView.measure(makeMeasureSpec(100, EXACTLY), makeMeasureSpec(100, EXACTLY)); assertThat(mLithoView.getMeasuredWidth()).isEqualTo(100); assertThat(mLithoView.getMeasuredHeight()).isEqualTo(100); assertThat(mLithoView.getComponentTree().getMainThreadLayoutState()).isNull(); mLithoView.layout(0, 0, 50, 50); final LayoutState layoutState = mLithoView.getComponentTree().getMainThreadLayoutState(); assertThat(layoutState).isNotNull(); assertThat(layoutState.isCompatibleSize(50, 50)).isTrue(); }
@Test public void testComponentTreeReleaseClearsView() { Component component = TestDrawableComponent.create(mContext) .build(); ComponentTree componentTree = create( mContext, component) .build(); LithoView lithoView = new LithoView(mContext); lithoView.setComponentTree(componentTree); assertThat(componentTree).isEqualTo(lithoView.getComponentTree()); componentTree.release(); assertThat(lithoView.getComponentTree()).isNull(); }
@Test public void testMountUnmountWithNewOrientation() { mContext.getResources().getConfiguration().orientation = ORIENTATION_PORTRAIT; final TestComponent firstComponent = create(mContext).build(); final LithoView lithoView = mountComponent(mContext, Column.create(mContext).child(firstComponent).build()); assertThat(firstComponent.wasOnMountCalled()).isTrue(); assertThat(firstComponent.wasOnBindCalled()).isTrue(); assertThat(firstComponent.wasOnUnmountCalled()).isFalse(); mContext.getResources().getConfiguration().orientation = ORIENTATION_LANDSCAPE; final TestComponent secondComponent = create(mContext).build(); lithoView.getComponentTree().setRoot(Column.create(mContext).child(secondComponent).build()); assertThat(secondComponent.wasOnMountCalled()).isTrue(); assertThat(secondComponent.wasOnBindCalled()).isTrue(); assertThat(firstComponent.wasOnUnbindCalled()).isTrue(); assertThat(firstComponent.wasOnUnmountCalled()).isTrue(); }
@Test public void testMountUnmountWithNoShouldUpdate() { final TestComponent firstComponent = create(mContext) .build(); final LithoView lithoView = mountComponent(mContext, Column.create(mContext).child(firstComponent).build()); assertThat(firstComponent.wasOnMountCalled()).isTrue(); assertThat(firstComponent.wasOnBindCalled()).isTrue(); assertThat(firstComponent.wasOnUnmountCalled()).isFalse(); final TestComponent secondComponent = create(mContext) .build(); lithoView.getComponentTree().setRoot(Column.create(mContext).child(secondComponent).build()); assertThat(secondComponent.wasOnMountCalled()).isFalse(); assertThat(secondComponent.wasOnBindCalled()).isTrue(); assertThat(firstComponent.wasOnUnmountCalled()).isFalse(); }
@Test public void testMountUnmountWithNoShouldUpdateAndDifferentMeasures() { final TestComponent firstComponent = create(mContext) .build(); final LithoView lithoView = mountComponent( new LithoView(mContext), ComponentTree.create(mContext, Column.create(mContext).child(firstComponent).build()) .build(), makeMeasureSpec(100, AT_MOST), makeMeasureSpec(100, AT_MOST)); assertThat(firstComponent.wasOnMountCalled()).isTrue(); assertThat(firstComponent.wasOnBindCalled()).isTrue(); assertThat(firstComponent.wasOnUnmountCalled()).isFalse(); final TestComponent secondComponent = create(mContext) .build(); lithoView .getComponentTree() .setRoot(Column.create(mContext).child(secondComponent).widthPx(10).heightPx(10).build()); assertThat(lithoView.isLayoutRequested()).isTrue(); assertThat(secondComponent.wasOnMountCalled()).isFalse(); assertThat(secondComponent.wasOnBindCalled()).isFalse(); assertThat(firstComponent.wasOnUnmountCalled()).isFalse(); }
@Test public void testRebindWithNoShouldUpdateAndSameMeasures() { final TestComponent firstComponent = create(mContext) .build(); final LithoView lithoView = mountComponent( new LithoView(mContext), ComponentTree.create(mContext, Column.create(mContext).child(firstComponent).build()) .build(), makeMeasureSpec(100, EXACTLY), makeMeasureSpec(100, EXACTLY)); assertThat(firstComponent.wasOnMountCalled()).isTrue(); assertThat(firstComponent.wasOnBindCalled()).isTrue(); assertThat(firstComponent.wasOnUnmountCalled()).isFalse(); final TestComponent secondComponent = create(mContext) .build(); lithoView .getComponentTree() .setRoot(Column.create(mContext).child(secondComponent).widthPx(10).heightPx(10).build()); assertThat(lithoView.isLayoutRequested()).isFalse(); assertThat(secondComponent.wasOnMountCalled()).isFalse(); assertThat(secondComponent.wasOnBindCalled()).isTrue(); assertThat(firstComponent.wasOnUnmountCalled()).isFalse(); }
@Test public void testMountUnmountWithShouldUpdate() { final TestComponent firstComponent = create(mContext) .unique() .build(); final LithoView lithoView = mountComponent(mContext, Column.create(mContext).child(firstComponent).build()); assertThat(firstComponent.wasOnMountCalled()).isTrue(); assertThat(firstComponent.wasOnBindCalled()).isTrue(); assertThat(firstComponent.wasOnUnmountCalled()).isFalse(); final TestComponent secondComponent = create(mContext) .unique() .build(); lithoView.getComponentTree().setRoot(Column.create(mContext).child(secondComponent).build()); assertThat(secondComponent.wasOnMountCalled()).isTrue(); assertThat(secondComponent.wasOnBindCalled()).isTrue(); assertThat(firstComponent.wasOnUnmountCalled()).isTrue(); }
@Test public void testMountUnmountWithSkipShouldUpdateAndRemount() { final TestComponent firstComponent = create(mContext) .color(BLACK) .build(); final LithoView lithoView = mountComponent(mContext, Column.create(mContext).child(firstComponent).build()); assertThat(firstComponent.wasOnMountCalled()).isTrue(); assertThat(firstComponent.wasOnBindCalled()).isTrue(); assertThat(firstComponent.wasOnUnmountCalled()).isFalse(); final TestComponent secondComponent = create(mContext) .color(WHITE) .build(); lithoView.getComponentTree().setRoot(Column.create(mContext).child(secondComponent).build()); assertThat(secondComponent.wasOnMountCalled()).isTrue(); assertThat(secondComponent.wasOnBindCalled()).isTrue(); assertThat(firstComponent.wasOnUnmountCalled()).isTrue(); }
@Test public void testMountUnmountWithSkipShouldUpdate() { final TestComponent firstComponent = create(mContext) .color(BLACK) .build(); final LithoView lithoView = mountComponent(mContext, Column.create(mContext).child(firstComponent).build()); assertThat(firstComponent.wasOnMountCalled()).isTrue(); assertThat(firstComponent.wasOnBindCalled()).isTrue(); assertThat(firstComponent.wasOnUnmountCalled()).isFalse(); final TestComponent secondComponent = create(mContext) .color(BLACK) .build(); lithoView.getComponentTree().setRoot(Column.create(mContext).child(secondComponent).build()); assertThat(secondComponent.wasOnMountCalled()).isFalse(); assertThat(secondComponent.wasOnBindCalled()).isTrue(); assertThat(firstComponent.wasOnUnmountCalled()).isFalse(); }
@Test public void testRemountsWithNewInputOnSameLayout() { final LithoView lithoView = mountComponent( mContext, create(mContext) .color(BLACK) .build()); shadowOf(lithoView).callOnAttachedToWindow(); assertThat(lithoView.getDrawables()).hasSize(1); assertThat(((ColorDrawable) lithoView.getDrawables().get(0)).getColor()).isEqualTo(BLACK); lithoView.getComponentTree().setRoot( create(mContext) .color(YELLOW) .build()); assertThat(lithoView.getDrawables()).hasSize(1); assertThat(((ColorDrawable) lithoView.getDrawables().get(0)).getColor()).isEqualTo(YELLOW); } }