in litho-sections-core/src/main/java/com/facebook/litho/sections/SectionTree.java [1768:1900]
private static void createNewTreeAndApplyStateUpdates(
SectionContext context,
@Nullable Section currentRoot,
Section nextRoot,
Map<String, List<StateContainer.StateUpdate>> pendingStateUpdates,
SectionsDebugLogger sectionsDebugLogger,
String sectionTreeTag) {
if (nextRoot == null) {
throw new IllegalStateException("Can't generate a subtree with a null root");
}
final boolean isTracing = ComponentsSystrace.isTracing();
if (isTracing) {
ComponentsSystrace.beginSection("createChildren:" + nextRoot.getSimpleName());
}
try {
nextRoot.setScopedContext(SectionContext.withScope(context, nextRoot));
if (currentRoot != null) {
nextRoot.setCount(currentRoot.getCount());
}
final boolean isNextRootDiffSection = nextRoot.isDiffSectionSpec();
if (!isNextRootDiffSection) {
nextRoot.populateTreeProps(context.getTreeProps());
}
final boolean shouldTransferState =
currentRoot != null && currentRoot.getClass().equals(nextRoot.getClass());
if (currentRoot == null || !shouldTransferState) {
nextRoot.createInitialState(nextRoot.getScopedContext());
nextRoot.createService(nextRoot.getScopedContext());
} else {
if (currentRoot.getService(currentRoot) == null) {
nextRoot.createService(nextRoot.getScopedContext());
if (nextRoot.getService(nextRoot) != null) {
final String errorMessage =
"We were about to transfer a null service from "
+ currentRoot
+ " to "
+ nextRoot
+ " while the later created a non-null service";
ComponentsReporter.emitMessage(
ComponentsReporter.LogLevel.ERROR, NULL_TO_NON_NULL_SERVICE_TRANSFER, errorMessage);
}
} else {
nextRoot.transferService(nextRoot.getScopedContext(), currentRoot, nextRoot);
}
nextRoot.transferState(currentRoot.getStateContainer(), nextRoot.getStateContainer());
}
// TODO: t18544409 Make sure this is absolutely the best solution as this is an anti-pattern
final List<StateContainer.StateUpdate> stateUpdates =
pendingStateUpdates.get(nextRoot.getGlobalKey());
if (stateUpdates != null) {
final StateContainer stateContainer = nextRoot.getStateContainer();
for (int i = 0, size = stateUpdates.size(); i < size; i++) {
stateContainer.applyStateUpdate(stateUpdates.get(i));
}
LithoStats.incrementSectionAppliedStateUpdateCountBy(stateUpdates.size());
if (nextRoot.shouldComponentUpdate(currentRoot, nextRoot)) {
nextRoot.invalidate();
}
}
if (!isNextRootDiffSection) {
final Map<String, Pair<Section, Integer>> currentComponentChildren =
currentRoot == null || currentRoot.isDiffSectionSpec()
? null
: Section.acquireChildrenMap(currentRoot);
final TreeProps parentTreeProps = context.getTreeProps();
context.setTreeProps(nextRoot.getTreePropsForChildren(context, parentTreeProps));
final ComponentsLogger logger = context.getLogger();
final PerfEvent logEvent =
SectionsLogEventUtils.getSectionsPerformanceEvent(
context, EVENT_SECTIONS_ON_CREATE_CHILDREN, null, nextRoot);
nextRoot.setChildren(nextRoot.createChildren(nextRoot.getScopedContext()));
if (logger != null && logEvent != null) {
logger.logPerfEvent(logEvent);
}
final List<Section> nextRootChildren = nextRoot.getChildren();
for (int i = 0, size = nextRootChildren.size(); i < size; i++) {
final Section child = nextRootChildren.get(i);
child.setParent(nextRoot);
final String childKey = child.getKey();
if (TextUtils.isEmpty(childKey)) {
final String errorMessage =
"Your Section "
+ child.getSimpleName()
+ " has an empty key. Please specify a key.";
throw new IllegalStateException(errorMessage);
}
final String globalKey = nextRoot.getGlobalKey() + childKey;
child.generateKeyAndSet(nextRoot.getScopedContext(), globalKey);
child.setScopedContext(SectionContext.withScope(context, child));
final Pair<Section, Integer> valueAndIndex =
currentComponentChildren == null
? null
: currentComponentChildren.get(child.getGlobalKey());
final Section currentChild = valueAndIndex != null ? valueAndIndex.first : null;
createNewTreeAndApplyStateUpdates(
context,
currentChild,
child,
pendingStateUpdates,
sectionsDebugLogger,
sectionTreeTag);
}
final TreeProps contextTreeProps = context.getTreeProps();
if (contextTreeProps != parentTreeProps) {
context.setTreeProps(parentTreeProps);
}
}
} finally {
if (isTracing) {
ComponentsSystrace.endSection();
}
}
}