void mount()

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();
    }
  }