in litho-core/src/main/java/com/facebook/litho/MountState.java [258:466]
void mount(
LayoutState layoutState, @Nullable Rect localVisibleRect, boolean processVisibilityOutputs) {
final ComponentTree componentTree = mLithoView.getComponentTree();
final boolean isIncrementalMountEnabled = componentTree.isIncrementalMountEnabled();
final boolean isVisibilityProcessingEnabled =
componentTree.isVisibilityProcessingEnabled() && processVisibilityOutputs;
assertMainThread();
if (layoutState == null) {
throw new IllegalStateException("Trying to mount a null layoutState");
}
final boolean shouldIncrementallyMount =
isIncrementalMountEnabled
&& localVisibleRect != null
&& !mPreviousLocalVisibleRect.isEmpty()
&& localVisibleRect.left == mPreviousLocalVisibleRect.left
&& localVisibleRect.right == mPreviousLocalVisibleRect.right;
if (mVisibilityExtension != null && mIsDirty) {
mVisibilityExtension.beforeMount(mVisibilityExtensionState, layoutState, localVisibleRect);
}
if (mTransitionsExtension != null && mIsDirty) {
mTransitionsExtension.beforeMount(mTransitionsExtensionState, layoutState, localVisibleRect);
}
mLayoutState = layoutState;
if (mIsMounting) {
ComponentsReporter.emitMessage(
ComponentsReporter.LogLevel.FATAL,
INVALID_REENTRANT_MOUNTS,
"Trying to mount while already mounting! "
+ getMountItemDebugMessage(mRootHostMountItem));
}
mIsMounting = true;
final boolean isTracing = RenderCoreSystrace.isEnabled();
if (isTracing) {
// Equivalent to RCMS MountState.mount
if (!shouldIncrementallyMount) {
RenderCoreSystrace.beginSection("MountState.mount");
}
ComponentsSystrace.beginSectionWithArgs(
"LMS."
+ (shouldIncrementallyMount ? "incrementalMount" : "mount")
+ (mIsDirty ? "Dirty" : "")
+ ": "
+ componentTree.getSimpleName())
.arg("treeId", layoutState.getComponentTreeId())
.arg("component", componentTree.getSimpleName())
.arg("logTag", componentTree.getContext().getLogTag())
.flush();
}
final ComponentsLogger logger = componentTree.getContext().getLogger();
final int componentTreeId = layoutState.getComponentTreeId();
if (componentTreeId != mLastMountedComponentTreeId) {
// If we're mounting a new ComponentTree, don't keep around and use the previous LayoutState
// since things like transition animations aren't relevant.
clearLastMountedLayoutState();
}
final PerfEvent mountPerfEvent =
logger == null
? null
: LogTreePopulator.populatePerfEventFromLogger(
componentTree.getContext(),
logger,
logger.newPerformanceEvent(componentTree.getContext(), EVENT_MOUNT));
if (mIsDirty) {
// Prepare the data structure for the new LayoutState and removes mountItems
// that are not present anymore if isUpdateMountInPlace is enabled.
if (mountPerfEvent != null) {
mountPerfEvent.markerPoint("PREPARE_MOUNT_START");
}
prepareMount(layoutState, mountPerfEvent);
if (mountPerfEvent != null) {
mountPerfEvent.markerPoint("PREPARE_MOUNT_END");
}
}
mMountStats.reset();
if (mountPerfEvent != null && logger.isTracing(mountPerfEvent)) {
mMountStats.enableLogging();
}
if (shouldIncrementallyMount) {
performIncrementalMount(layoutState, localVisibleRect, processVisibilityOutputs);
} else {
final MountItem rootMountItem = mIndexToItemMap.get(ROOT_HOST_ID);
final Rect absoluteBounds = new Rect();
for (int i = 0, size = layoutState.getMountableOutputCount(); i < size; i++) {
final RenderTreeNode node = layoutState.getMountableOutputAt(i);
final LayoutOutput layoutOutput = getLayoutOutput(node);
final Component component = layoutOutput.getComponent();
final MountItem currentMountItem = getItemAt(i);
final boolean isMounted = currentMountItem != null;
final boolean isRoot = currentMountItem != null && currentMountItem == rootMountItem;
final boolean isMountable =
!isIncrementalMountEnabled
|| isMountedHostWithChildContent(currentMountItem)
|| Rect.intersects(localVisibleRect, node.getAbsoluteBounds(absoluteBounds))
|| isAnimationLocked(node)
|| isRoot;
if (isMountable && !isMounted) {
mountLayoutOutput(i, node, layoutOutput, layoutState);
} else if (!isMountable && isMounted) {
unmountItem(i, mHostsByMarker);
} else if (isMounted) {
if (mIsDirty || (isRoot && mNeedsRemount)) {
final boolean useUpdateValueFromLayoutOutput =
mLastMountedLayoutState != null
&& mLastMountedLayoutState.getId() == layoutState.getPreviousLayoutStateId();
final long startTime = System.nanoTime();
final boolean itemUpdated =
updateMountItemIfNeeded(
node,
currentMountItem,
useUpdateValueFromLayoutOutput,
isIncrementalMountEnabled,
processVisibilityOutputs);
if (mMountStats.isLoggingEnabled) {
if (itemUpdated) {
mMountStats.updatedNames.add(component.getSimpleName());
mMountStats.updatedTimes.add((System.nanoTime() - startTime) / NS_IN_MS);
mMountStats.updatedCount++;
} else {
mMountStats.noOpCount++;
}
}
} else {
if (isIncrementalMountEnabled
&& component.hasChildLithoViews()
&& !mLithoView.skipNotifyVisibleBoundsChangedCalls()) {
mountItemIncrementally(currentMountItem, processVisibilityOutputs);
}
}
}
}
if (isIncrementalMountEnabled) {
setupPreviousMountableOutputData(layoutState, localVisibleRect);
}
}
if (isTracing) {
if (!shouldIncrementallyMount) {
RenderCoreSystrace.endSection();
}
ComponentsSystrace.endSection(); // beginSectionWithArgs
RenderCoreSystrace.beginSection("RenderCoreExtension.afterMount");
}
afterMountMaybeUpdateAnimations();
if (isVisibilityProcessingEnabled) {
if (isTracing) {
RenderCoreSystrace.beginSection("LMS.processVisibilityOutputs");
}
if (mountPerfEvent != null) {
mountPerfEvent.markerPoint("EVENT_PROCESS_VISIBILITY_OUTPUTS_START");
}
processVisibilityOutputs(localVisibleRect, mIsDirty);
if (mountPerfEvent != null) {
mountPerfEvent.markerPoint("EVENT_PROCESS_VISIBILITY_OUTPUTS_END");
}
if (isTracing) {
RenderCoreSystrace.endSection();
}
}
final boolean wasDirty = mIsDirty;
final boolean hadPreviousComponentTree =
(mLastMountedComponentTreeId != ComponentTree.INVALID_ID);
mIsDirty = false;
mNeedsRemount = false;
if (localVisibleRect != null) {
mPreviousLocalVisibleRect.set(localVisibleRect);
}
clearLastMountedLayoutState();
mLastMountedComponentTreeId = componentTreeId;
mLastMountedLayoutState = layoutState;
processTestOutputs(layoutState);
if (mountPerfEvent != null) {
logMountPerfEvent(logger, mountPerfEvent, wasDirty, hadPreviousComponentTree);
}
LithoStats.incrementComponentMountCount();
mIsMounting = false;
if (isTracing) {
RenderCoreSystrace.endSection();
}
}