Released documentation snapshot. This immutable manual describes
viewcompose-ui-contract:0.1.0-alpha03from source revision2d7c8561. For current guidance, open the current module catalog.
UI Contract
viewcompose-ui-contract defines the platform-neutral model shared by ViewCompose DSL modules and
renderers: immutable virtual nodes and node specifications, ordered modifiers, environment values,
layout units, interaction contracts, and renderer-connected state for lazy collections and pagers.
Use it directly when building a custom renderer, host bridge, tooling integration, or reusable API
that exposes ViewCompose contract types. Application UI normally receives it transitively through
viewcompose-widget-core.
This module does not compose a DSL tree, create Android View instances, reconcile nodes, schedule
frames, or integrate Android lifecycle and saved state. Those responsibilities belong to the
runtime, widget, renderer, and host modules.
Artifact and stability
dependencies {
implementation("com.viewcompose:viewcompose-ui-contract:0.1.0-alpha01")
}
- Stability: Alpha. Source and binary compatibility may change between alpha releases.
- Platform: Kotlin/JVM, compiled with the Java 11 toolchain; no Android SDK or AndroidX dependency.
- Transitively exposed contract families: platform-neutral text/editing from
viewcompose-text-coreand drawing models fromviewcompose-graphics-core; both appear in public UI contract signatures. viewcompose-runtimeremains an implementation dependency.- Build baseline for this release: Kotlin 2.0.21.
Minimal contract usage
val gap = VNode(
type = NodeType.Spacer,
key = "content-gap",
spec = EmptyNodeSpec,
modifier = Modifier
.size(24.dp)
.testTag("content-gap"),
)
This creates a renderer-neutral semantic node. A compatible renderer resolves NodeType.Spacer,
validates its EmptyNodeSpec, interprets the modifier chain in order, and owns any native object
created for the node.
Principal APIs
VNodeandNodeTypedefine immutable tree content and renderer dispatch.NodeSpecand its concrete property snapshots define the supported renderer inputs.Modifiercarries ordered layout, drawing, interaction, semantics, focus, and parent-data elements.UiEnvironmentValuescaptures density, locale tags, and logical layout direction for a subtree.LazyListStateand pager state bridge platform scrolling to observable runtime state.FocusRequesterandNestedScrollDispatcherdefine explicit renderer attachment boundaries for focus and nested scrolling.ImageSource,UiImageRequest, andUiImageLoaderdefine portable image sources, request policy, platform targets, and disposable load handles.- The unit, shape, graphics, key-input, gesture, semantics, and tooling packages complete the platform-neutral vocabulary used across ViewCompose modules.
The complete generated reference is available under the
viewcompose-ui-contract API tree.
Because the current line is alpha, the documentation site intentionally does not expose a stable
latest alias.
Contract and lifecycle rules
VNode.typeandVNode.specare a registry-level pair. Construction is intentionally cheap and does not validate compatibility; a renderer must reject an unsupported pair deterministically.- A node specification is an immutable render snapshot. Callbacks may capture mutable application state, but the spec itself must not be used as a native-object owner.
- Modifier order is semantic. Layout and parent-data collection, visual decoration, input, semantics, and drawing phases consume the ordered elements according to their documented phase rules; reordering elements may change behavior.
UiEnvironmentValuesis captured on every VNode subtree. A renderer must use the captured values instead of consulting unrelated process-global density, locale, or direction state.LazyListState, pager state, focus requesters, and nested-scroll dispatchers attach to one current renderer connector. Hosts must detach old connectors during replacement or disposal.- State and connector commands are thread-confined to the owning renderer thread. Android integrations use the main thread, and callbacks run synchronously unless a concrete contract says otherwise.
AndroidViewNodeProps.updateandonResetare replay-safe transaction callbacks. External one-shot work belongs inonCommit; resource cleanup belongs inonRelease.- Image loading is an optional capability.
UiImageLoaderis caller-owned, runs on the owning UI thread, and returns a handle for the started work. The renderer owns replacing and disposing the handle for a mounted image View; a loader must not retain that View after disposal. ImageSource.Urlaccepts only absolute HTTP(S) URLs;ImageSource.Uriaccepts absolute URIs for other loader-supported schemes.UiImageDecodeSize.Fixeduses positiveUiDpbounds. The renderer includes its capturedUiDensityinUiImageRequest, and adapters resolve those logical bounds to platform pixels without changing layout size.ImageSource.Modelrequires a caller-provided stable key. Its equality and diagnostic text must not depend on the raw model payload, so adapters can accept arbitrary platform-specific models without leaking them into logs or persistence.- A
UiImageRequestExtensionis identified by its concrete runtime type plusstableKey. Adapters ignore extension types they do not own, and callers must change the key when load behavior changes.
Collection prefetch, native cache sizing, motion, and shared-pool values are renderer hints rather than semantic state. A platform may clamp or ignore an unsupported optimization without changing the declared content.
Related documentation
- Node specifications and renderer registration
- Modifier architecture
- Current architecture and module boundaries
- Lazy collection guide
- Focus and input guide
- Nested scrolling guide
- Image loading guide
- Source documentation and API comment standard
Compatibility notes
The 0.1.0-alpha01 line establishes the first public renderer contract. Adding a NodeType, a
concrete NodeSpec, or a modifier element can require a renderer update even when application DSL
source remains unchanged. Custom renderers should fail clearly for unknown contracts and should not
persist enum ordinals, sealed-subtype names, tooling metadata, native view identities, or callback
instances as long-lived external data.