private static void performIncrementalMount()

in litho-rendercore-incremental-mount/src/main/java/com/facebook/rendercore/incrementalmount/IncrementalMountExtension.java [370:499]


  private static void performIncrementalMount(
      final ExtensionState<IncrementalMountExtensionState> extensionState,
      final Rect localVisibleRect) {
    final IncrementalMountExtensionState state = extensionState.getState();
    if (state.mInput == null) {
      return;
    }

    final boolean isTracing = RenderCoreSystrace.isEnabled();
    if (isTracing) {
      RenderCoreSystrace.beginSection("performIncrementalMount");
    }

    final List<IncrementalMountOutput> byTopBounds = state.mInput.getOutputsOrderedByTopBounds();
    final List<IncrementalMountOutput> byBottomBounds =
        state.mInput.getOutputsOrderedByBottomBounds();
    final int count = state.mInput.getIncrementalMountOutputCount();

    int itemsMounted = 0;
    int itemsUnmounted = 0;

    if (localVisibleRect.top >= 0 || state.mPreviousLocalVisibleRect.top >= 0) {
      // View is going on/off the top of the screen. Check the bottoms to see if there is anything
      // that has moved on/off the top of the screen.
      while (state.mPreviousBottomsIndex < count
          && localVisibleRect.top
              >= byBottomBounds.get(state.mPreviousBottomsIndex).getBounds().bottom) {

        final IncrementalMountOutput node = byBottomBounds.get(state.mPreviousBottomsIndex);
        final long id = node.getId();

        if (extensionState.ownsReference(id)) {
          extensionState.releaseMountReference(id, true);
          if (IncrementalMountExtensionConfigs.isDebugLoggingEnabled) {
            itemsUnmounted++;
          }
        }

        state.mPreviousBottomsIndex++;
      }

      while (state.mPreviousBottomsIndex > 0
          && localVisibleRect.top
              < byBottomBounds.get(state.mPreviousBottomsIndex - 1).getBounds().bottom) {

        final IncrementalMountOutput node = byBottomBounds.get(state.mPreviousBottomsIndex - 1);
        final long id = node.getId();

        // Item should still be in the view port.
        if (localVisibleRect.bottom
            >= byBottomBounds.get(state.mPreviousBottomsIndex - 1).getBounds().top) {
          if (!extensionState.ownsReference(id)) {
            extensionState.acquireMountReference(node.getId(), true);
            state.mComponentIdsMountedInThisFrame.add(id);
            if (IncrementalMountExtensionConfigs.isDebugLoggingEnabled) {
              itemsMounted++;
            }
          }
        }

        state.mPreviousBottomsIndex--;
      }
    }

    Host root = extensionState.getRootHost();
    final int height = root != null ? root.getHeight() : 0;
    if (localVisibleRect.bottom < height || state.mPreviousLocalVisibleRect.bottom < height) {
      // View is going on/off the bottom of the screen. Check the tops to see if there is anything
      // that has changed.
      while (state.mPreviousTopsIndex < count
          && localVisibleRect.bottom >= byTopBounds.get(state.mPreviousTopsIndex).getBounds().top) {

        final IncrementalMountOutput node = byTopBounds.get(state.mPreviousTopsIndex);
        final long id = node.getId();

        // Item should still be in the view port.
        if (localVisibleRect.top <= byTopBounds.get(state.mPreviousTopsIndex).getBounds().bottom) {
          if (!extensionState.ownsReference(id)) {
            extensionState.acquireMountReference(node.getId(), true);
            state.mComponentIdsMountedInThisFrame.add(id);
            if (IncrementalMountExtensionConfigs.isDebugLoggingEnabled) {
              itemsMounted++;
            }
          }
        }

        state.mPreviousTopsIndex++;
      }

      while (state.mPreviousTopsIndex > 0
          && localVisibleRect.bottom
              < byTopBounds.get(state.mPreviousTopsIndex - 1).getBounds().top) {

        final IncrementalMountOutput node = byTopBounds.get(state.mPreviousTopsIndex - 1);
        final long id = node.getId();

        if (extensionState.ownsReference(id)) {
          extensionState.releaseMountReference(id, true);
          if (IncrementalMountExtensionConfigs.isDebugLoggingEnabled) {
            itemsUnmounted++;
          }
        }

        state.mPreviousTopsIndex--;
      }
    }

    if (IncrementalMountExtensionConfigs.isDebugLoggingEnabled) {
      Log.d(
          DEBUG_TAG,
          "Updates: [Items Mounted=" + itemsMounted + ", Items Unmounted=" + itemsUnmounted + "]");
    }

    for (long id : state.mMountedOutputIdsWithNestedContent.keySet()) {
      if (state.mComponentIdsMountedInThisFrame.contains(id)) {
        continue;
      }

      final Object content = state.mMountedOutputIdsWithNestedContent.get(id);
      if (content != null) {
        recursivelyNotifyVisibleBoundsChanged(extensionState, id, content);
      }
    }

    state.mComponentIdsMountedInThisFrame.clear();

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