static LayoutState calculate()

in litho-core/src/main/java/com/facebook/litho/LayoutState.java [1109:1293]


  static LayoutState calculate(
      ComponentContext c,
      Component component,
      @Nullable LayoutStateFuture layoutStateFuture,
      StateHandler stateHandler,
      int componentTreeId,
      int widthSpec,
      int heightSpec,
      int layoutVersion,
      boolean shouldGenerateDiffTree,
      @Nullable LayoutState currentLayoutState,
      @CalculateLayoutSource int source,
      @Nullable String extraAttribution) {

    final ComponentsLogger logger = c.getLogger();

    final boolean isTracing = ComponentsSystrace.isTracing();
    if (isTracing) {
      if (extraAttribution != null) {
        ComponentsSystrace.beginSection("extra:" + extraAttribution);
      }
      ComponentsSystrace.beginSectionWithArgs(
              new StringBuilder("LayoutState.calculate_")
                  .append(component.getSimpleName())
                  .append("_")
                  .append(layoutSourceToString(source))
                  .toString())
          .arg("treeId", componentTreeId)
          .arg("rootId", component.getId())
          .arg("widthSpec", SizeSpec.toString(widthSpec))
          .arg("heightSpec", SizeSpec.toString(heightSpec))
          .flush();
    }

    final @Nullable DiffNode diffTreeRoot;
    final @Nullable LithoNode currentRoot;
    final @Nullable LayoutStateContext currentLayoutStateContext;

    final boolean isReconcilable;

    if (currentLayoutState != null) {
      synchronized (currentLayoutState) {
        diffTreeRoot = currentLayoutState.mDiffTreeRoot;
        currentRoot = currentLayoutState.mRoot;
        currentLayoutStateContext = currentLayoutState.getLayoutStateContext();
        isReconcilable =
            isReconcilable(c, component, Preconditions.checkNotNull(stateHandler), currentRoot);
        if (!isReconcilable) { // Release the current InternalNode tree if it is not reconcilable.
          currentLayoutState.mRoot = null;
          currentLayoutState.mLayoutResult = null;
        }
      }
    } else {
      diffTreeRoot = null;
      currentRoot = null;
      currentLayoutStateContext = null;
      isReconcilable = false;
    }

    final LayoutState layoutState;
    final LayoutStateContext layoutStateContext;

    try {
      final PerfEvent logLayoutState =
          logger != null
              ? LogTreePopulator.populatePerfEventFromLogger(
                  c, logger, logger.newPerformanceEvent(c, EVENT_CALCULATE_LAYOUT_STATE))
              : null;
      if (logLayoutState != null) {
        logLayoutState.markerAnnotate(PARAM_COMPONENT, component.getSimpleName());
        logLayoutState.markerAnnotate(PARAM_LAYOUT_STATE_SOURCE, layoutSourceToString(source));
        logLayoutState.markerAnnotate(PARAM_IS_BACKGROUND_LAYOUT, !ThreadUtils.isMainThread());
        logLayoutState.markerAnnotate(PARAM_TREE_DIFF_ENABLED, diffTreeRoot != null);
        logLayoutState.markerAnnotate(PARAM_ATTRIBUTION, extraAttribution);
        logLayoutState.markerAnnotate(PARAM_LAYOUT_VERSION, layoutVersion);
      }

      layoutState =
          new LayoutState(
              c, component, stateHandler, layoutStateFuture, currentLayoutState, diffTreeRoot);

      layoutStateContext = layoutState.getLayoutStateContext();
      if (logLayoutState != null) {
        layoutStateContext.setPerfEvent(logLayoutState);
      }

      // Detect errors internal to components
      Component.markLayoutStarted(component, layoutStateContext);

      final LithoNode layoutCreatedInWillRender =
          component.consumeLayoutCreatedInWillRender(currentLayoutStateContext, c);

      c.setLayoutStateContext(layoutStateContext);

      layoutState.mShouldGenerateDiffTree = shouldGenerateDiffTree;
      layoutState.mComponentTreeId = componentTreeId;
      layoutState.mLayoutVersion = layoutVersion;
      layoutState.mAccessibilityManager =
          (AccessibilityManager) c.getAndroidContext().getSystemService(ACCESSIBILITY_SERVICE);
      layoutState.mAccessibilityEnabled =
          AccessibilityUtils.isAccessibilityEnabled(layoutState.mAccessibilityManager);
      layoutState.mWidthSpec = widthSpec;
      layoutState.mHeightSpec = heightSpec;
      layoutState.mRootComponentName = component.getSimpleName();
      layoutState.mIsCreateLayoutInProgress = true;

      final @Nullable LithoLayoutResult root;
      if (layoutCreatedInWillRender == null) {

        final LayoutResultHolder holder =
            Layout.createAndMeasureComponent(
                layoutStateContext,
                c,
                component,
                isReconcilable
                    ? Preconditions.checkNotNull(currentRoot).getHeadComponentKey()
                    : null,
                widthSpec,
                heightSpec,
                isReconcilable,
                currentRoot,
                diffTreeRoot,
                logLayoutState);

        // Check if layout was interrupted.
        if (holder.wasLayoutInterrupted()) {
          layoutState.mPartiallyResolvedRoot =
              Preconditions.checkNotNull(holder.mPartiallyResolvedLayout);
          layoutState.mRootTransitionId = getTransitionIdForNode(holder.mPartiallyResolvedLayout);
          layoutState.mIsCreateLayoutInProgress = false;
          layoutState.mIsPartialLayoutState = true;
          if (logLayoutState != null) {
            Preconditions.checkNotNull(logger).logPerfEvent(logLayoutState);
          }

          return layoutState;
        } else {
          root = holder.mResult;
        }

      } else {
        root =
            Layout.measure(
                layoutStateContext,
                c,
                layoutCreatedInWillRender,
                widthSpec,
                heightSpec,
                diffTreeRoot);
      }

      final @Nullable LithoNode node = root != null ? root.getNode() : null;

      layoutState.mLayoutResult = root;
      layoutState.mRoot = node;
      layoutState.mRootTransitionId = getTransitionIdForNode(node);
      layoutState.mIsCreateLayoutInProgress = false;

      if (logLayoutState != null) {
        logLayoutState.markerPoint("start_collect_results");
      }

      setSizeAfterMeasureAndCollectResults(c, layoutState);

      layoutStateContext.releaseReference();

      if (logLayoutState != null) {
        logLayoutState.markerPoint("end_collect_results");
        Preconditions.checkNotNull(logger).logPerfEvent(logLayoutState);
      }
    } finally {
      if (isTracing) {
        ComponentsSystrace.endSection();
        if (extraAttribution != null) {
          ComponentsSystrace.endSection();
        }
      }
    }
    LithoStats.incrementComponentCalculateLayoutCount();
    if (ThreadUtils.isMainThread()) {
      LithoStats.incrementComponentCalculateLayoutOnUICount();
    }

    return layoutState;
  }