public void mount()

in litho-rendercore/src/main/java/com/facebook/rendercore/MountState.java [97:248]


  public void mount(RenderTree renderTree) {
    if (renderTree == null) {
      throw new IllegalStateException("Trying to mount a null RenderTreeNode");
    }

    if (mIsMounting) {
      throw new IllegalStateException("Trying to mount while already mounting!");
    }

    final RenderTree previousRenderTree = mRenderTree;

    if (!updateRenderTree(renderTree)) {
      return;
    }

    final boolean isTracing = RenderCoreSystrace.isEnabled();
    if (isTracing) {
      RenderCoreSystrace.beginSection("MountState.mount");
      RenderCoreSystrace.beginSection("RenderCoreExtension.beforeMount");
    }

    mIsMounting = true;
    RenderCoreExtension.beforeMount(mRootHost, mMountDelegate, mRenderTree.getExtensionResults());

    if (isTracing) {
      RenderCoreSystrace.endSection();
      RenderCoreSystrace.beginSection("MountState.prepareMount");
    }

    prepareMount(previousRenderTree);

    if (isTracing) {
      RenderCoreSystrace.endSection();
    }

    // TODO: Remove this additional logging when root cause of crash in mountRenderUnit is found.
    // We only want to collect logs when we're not ensuring the parent is mounted. When false,
    // we will throw an exception that contains these logs. The StringBuilder is not needed when
    // mEnsureParentMount is true.
    @Nullable final StringBuilder mountLoopLogBuilder;
    if (!mEnsureParentMounted) {
      mountLoopLogBuilder = new StringBuilder();
      mountLoopLogBuilder.append("Start of mount loop log:\n");
    } else {
      mountLoopLogBuilder = null;
    }

    // Starting from 1 as the RenderTreeNode in position 0 always represents the root which is
    // handled in prepareMount()
    for (int i = 1, size = renderTree.getMountableOutputCount(); i < size; i++) {
      final RenderTreeNode renderTreeNode = renderTree.getRenderTreeNodeAtIndex(i);

      final boolean isMountable = isMountable(renderTreeNode, i);
      final MountItem currentMountItem =
          mIdToMountedItemMap.get(renderTreeNode.getRenderUnit().getId());
      boolean isMounted = currentMountItem != null;

      // There is a bug (T99579422) happening where we try to incorrectly update an already mounted
      // render unit.
      // TODO: T101249557
      if (isMounted) {
        final RenderUnit currentRenderUnit = currentMountItem.getRenderUnit();
        boolean needsRecovery = false;
        // The old render unit we try to update is the root host which should not be updated (that's
        // why we start from index 1).
        if (currentRenderUnit.getId() != renderTreeNode.getRenderUnit().getId()) {
          needsRecovery = true;
          ErrorReporter.getInstance()
              .report(
                  LogLevel.ERROR,
                  TAG,
                  "The current render unit id does not match the new one. "
                      + " index: "
                      + i
                      + " mountableOutputCounts: "
                      + renderTree.getMountableOutputCount()
                      + " currentRenderUnitId: "
                      + currentRenderUnit.getId()
                      + " newRenderUnitId: "
                      + renderTreeNode.getRenderUnit().getId(),
                  null,
                  0,
                  null);
        }

        // The new render unit is not the same type as the old one.
        if (!currentRenderUnit
            .getRenderContentType()
            .equals(renderTreeNode.getRenderUnit().getRenderContentType())) {
          needsRecovery = true;
          ErrorReporter.getInstance()
              .report(
                  LogLevel.ERROR,
                  TAG,
                  "Trying to update a MountItem with different ContentType. "
                      + "index: "
                      + i
                      + " currentRenderUnitId: "
                      + currentRenderUnit.getId()
                      + " newRenderUnitId: "
                      + renderTreeNode.getRenderUnit().getId()
                      + " currentRenderUnitContentType: "
                      + currentRenderUnit.getRenderContentType()
                      + " newRenderUnitContentType: "
                      + renderTreeNode.getRenderUnit().getRenderContentType(),
                  null,
                  0,
                  null);
        }
        if (needsRecovery) {
          recreateMountedItemMap(previousRenderTree);
          // reset the loop to start over.
          i = 1;
          continue;
        }
      }

      if (!mEnsureParentMounted) {
        mountLoopLogBuilder.append(
            String.format(
                Locale.US,
                "Processing index %d: isMountable = %b, isMounted = %b\n",
                i,
                isMountable,
                isMounted));
      }

      if (!isMountable) {
        if (isMounted) {
          unmountItemRecursively(currentMountItem.getRenderTreeNode().getRenderUnit().getId());
        }
      } else if (!isMounted) {
        mountRenderUnit(renderTreeNode, mountLoopLogBuilder);
      } else {
        updateMountItemIfNeeded(mMountDelegate, mContext, renderTreeNode, currentMountItem);
      }
    }

    mNeedsRemount = false;
    mIsMounting = false;

    if (isTracing) {
      RenderCoreSystrace.endSection();
      RenderCoreSystrace.beginSection("RenderCoreExtension.afterMount");
    }

    RenderCoreExtension.afterMount(mMountDelegate);

    if (isTracing) {
      RenderCoreSystrace.endSection();
    }
  }