Lesson 1

Positional identity and explicit key groups

Predict how Compose matches groups when control flow and repeated calls change.

3 min readUpdated Jul 12, 2026

Status: The matching model is Durable . Generated integer keys and composer method names are Version-specific observations at the pinned revisions above. This is not a promise that every compiler release emits identical groups.

Outcome

Given a conditional or loop, you should be able to predict when a remembered value stays attached to the same logical work and when it is matched to a different position.

A group has a place and, sometimes, data identity

The compiler turns composable structure into groups consumed by Composer. For compiler-generated replace groups, the key argument is derived from source information. The pinned compiler computes a source key from the function and source offsets, then emits it into group calls (ComposableFunctionBodyTransformer.kt). This is a call-site key: it tells the runtime which source location produced the group.

A repeated call at one source location still needs a way to distinguish its siblings. Without an explicit data key, the repeated invocations are reconciled positionally. Insert an item at the front and later siblings now occupy different positions. Their groups may still have the same call-site key, but the position no longer names the same item.

The key composable changes that second part. The compiler lowers it to a movable group with a source key and a data key. Composer.startMovableGroup documents the pair: the source key comes from the call site, while the data key comes from key’s arguments (Composer.kt). The runtime can then move a matching group rather than treating every later sibling as a replacement.

for (message in messages) {
    key(message.id) {
        MessageRow(message)
    }
}

Here message.id does not need to be unique across the entire application. It must be unique among the key invocations at this point in this parent. AndroidX’s key documentation makes the same local rule and warns that duplicate keys can reuse children and local state unintentionally (Composables.kt).

Do not confuse a key with a hash display

Compose also exposes currentCompositeKeyHashCode. It is a hash that can correlate an external value with a composition location; it is not the complete reconciliation record. The API documentation explicitly says that collisions remain possible and that repeated content without enough key information may not be uniquely identifiable (CompositeKeyHashCode.kt). Use it for the narrow external-mapping use case, not as a globally unique identity token.

Diagram
flowchart LR
    CallSite[Compiler source key] --> Group[Runtime group]
    DataKey[Optional key data] --> Group
    Position[Sibling position] --> Group
    Group --> Slots[Remembered slots]

Reproduce the prediction

Create a small composition whose loop records an object from remember { Token(id) }. First render [A, B, C], then insert X before A. Log each row’s displayed id and token id. Repeat with key(id). The first run demonstrates positional matching; the second demonstrates data-keyed movement. Keep the experiment’s compiler/runtime revision pinned because the group protocol is implementation evidence, not a public slot-table layout.

Check yourself

Why is key(id) locally unique rather than globally unique? In the diagram, which input changes when two separate loops both use the same id values?

Source notes

ClaimDirect evidenceStatus
Compiler source offsets become generated group keysPinned ComposableFunctionBodyTransformer.ktVersion-specific
Movable groups combine a compiler key with a data keyPinned Composer.ktDurable Version-specific
key is locally scoped and duplicate keys are unsafePinned Composables.ktDurable
Composite key hashes can collide or lack informationPinned CompositeKeyHashCode.ktVersion-specific

Freshness

Refresh this lesson when compiler source-key generation, replace/movable group lowering, or the key contract changes. Recheck the Android Review history for Composer.kt before describing a changed protocol as durable.

Finished this lesson?

Your progress stays only in this browser.