Skip to content

Commit

Permalink
avoid key collisions for nested tree layout caching
Browse files Browse the repository at this point in the history
Summary: Piggybacking off of D55036892, we create an identifier object for all nested Litho components. This identifier is simply a wrapper around an integer tree id and acts as a stable reference key for caching the nested Litho component's layout state

Reviewed By: adityasharat

Differential Revision: D55020990

fbshipit-source-id: 49c2d32dd39646b63d92407bcec1b7380177104c
  • Loading branch information
Daniel Famakin authored and facebook-github-bot committed Mar 20, 2024
1 parent 9ee017c commit 123e28d
Showing 1 changed file with 32 additions and 10 deletions.
42 changes: 32 additions & 10 deletions litho-core/src/main/java/com/facebook/litho/NestedLithoPrimitive.kt
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ fun NestedLithoPrimitive(
): Pair<Primitive, ResolveResult> {

val (
treeId,
nestedTreeId,
androidContext,
config,
currentResolveResult,
Expand All @@ -88,7 +88,7 @@ fun NestedLithoPrimitive(

val componentContext: ComponentContext =
createdNestedTreeComponentContext(
treeId = treeId,
treeId = nestedTreeId.id,
androidContext = androidContext,
treeProps = treeProps,
lithoConfiguration = config,
Expand All @@ -101,7 +101,7 @@ fun NestedLithoPrimitive(

val result =
NestedLithoTree.resolve(
treeId,
nestedTreeId.id,
componentContext,
component,
treeProps,
Expand All @@ -117,7 +117,7 @@ fun NestedLithoPrimitive(

// binder to clean up the content before returning it to the pool
withDescription("final-unmount") {
bind(treeId) { content ->
bind(nestedTreeId.id) { content ->
onUnbind {
content.currentLayoutState?.cleanup()
content.resetLayoutState()
Expand All @@ -126,7 +126,7 @@ fun NestedLithoPrimitive(
}

withDescription("lifecycle-provider-release") {
bind(treeId) { _ -> onUnbind { lifecycleProvider.release() } }
bind(nestedTreeId.id) { _ -> onUnbind { lifecycleProvider.release() } }
}

// binder to bind the layout state with the Litho Render Tree View
Expand Down Expand Up @@ -156,7 +156,11 @@ fun NestedLithoPrimitive(

return Pair(
Primitive(
layoutBehavior = LithoLayoutBehavior(result = result),
layoutBehavior =
LithoLayoutBehavior(
result = result,
cacheKey = resolveContext.treeId,
resolveContext.usePreviousLayoutState),
mountBehavior = mountBehavior,
),
result,
Expand Down Expand Up @@ -196,10 +200,25 @@ fun createdNestedTreeComponentContext(
)
}

internal class LithoLayoutBehavior(val result: ResolveResult) : LayoutBehavior {
internal class LithoLayoutBehavior(
val result: ResolveResult,
private val cacheKey: NestedTreeId,
private val usePreviousLayoutState: Boolean,
) : LayoutBehavior {
override fun LayoutScope.layout(sizeConstraints: SizeConstraints): PrimitiveLayoutResult {
val layoutState =
NestedLithoTree.layout(result, sizeConstraints, previousLayoutData as LayoutState?)
val previousLayoutState: LayoutState? =
if (usePreviousLayoutState) {
layoutContext.layoutCache[cacheKey]
} else {
null
}

val layoutState = NestedLithoTree.layout(result, sizeConstraints, previousLayoutState)

if (usePreviousLayoutState) {
layoutContext.layoutCache.put(cacheKey, layoutState)
}

return PrimitiveLayoutResult(
width = layoutState.width,
height = layoutState.height,
Expand All @@ -210,7 +229,7 @@ internal class LithoLayoutBehavior(val result: ResolveResult) : LayoutBehavior {

@DataClassGenerate(toString = Mode.OMIT, equalsHashCode = Mode.KEEP)
data class NestedLithoResolveContext(
val treeId: Int,
val treeId: NestedTreeId,
val androidContext: Context,
val config: LithoConfiguration,
val currentResolveResult: ResolveResult?,
Expand All @@ -219,8 +238,11 @@ data class NestedLithoResolveContext(
val errorComponent: ((Component?) -> Unit) = { /* TODO: provide default implementation */},
val rootHostReference: NestedMountedViewReference = NestedMountedViewReference(),
val lifecycleProvider: NestedLithoTreeLifecycleProvider = NestedLithoTreeLifecycleProvider(),
val usePreviousLayoutState: Boolean,
)

class NestedTreeId(val id: Int)

fun interface StateUpdateRequester {
fun request(update: PendingStateUpdate)
}
Expand Down

0 comments on commit 123e28d

Please sign in to comment.