Skip to content

Compose Preview Issue #1683

Description

@Wadamzmail

Fix Compose Preview runtime dependency version mismatch

Problem

The Compose Preview runtime currently packages hardcoded Compose and Material3 dependencies:

val composeVersion = "1.6.0"
val material3Version = "1.2.0"

These dependencies are converted to DEX and bundled into AndroidIDE assets.

When a user project uses different Compose/Material3 versions, the Preview compiler may successfully compile the user's source code against the project's resolved dependencies, but the generated bytecode is executed against AndroidIDE's bundled Compose runtime.

This can cause runtime ABI mismatches such as:

java.lang.NoSuchMethodError:
No static method darkColorScheme-... in
androidx.compose.material3.ColorSchemeKt

For example:

User project:
Material3 1.x
      ↓
compilation
      ↓
bytecode expects method X

AndroidIDE Preview runtime:
Material3 1.2.0
      ↓
method X is missing
      ↓
NoSuchMethodError

Proposed solution

Instead of using hardcoded Compose dependency versions for the Preview runtime, use the resolved dependencies from the user's Gradle project.

The Preview pipeline should:

  1. Trigger a project build/sync when the required Compose DEX files are missing.
  2. Obtain the resolved Compose-related artifacts for the selected project variant from Gradle.
  3. Use the actual resolved AAR/JAR files rather than reconstructing dependencies from hardcoded versions.
  4. Extract "classes.jar" from AARs when necessary.
  5. Convert the resolved runtime classes to DEX using D8.
  6. Cache the resulting DEX files.
  7. Rebuild the cache when the resolved dependency set changes.

Conceptually:

User Project
     │
     ▼
Gradle dependency resolution
     │
     ▼
Resolved Compose artifacts
     │
     ├── runtime
     ├── ui
     ├── foundation
     ├── material3
     └── other required dependencies
     │
     ▼
Extract classes.jar
     │
     ▼
D8
     │
     ▼
Preview runtime DEX
     │
     ▼
Compose Preview

Cache invalidation

The DEX cache should not only check whether the DEX file exists.

A dependency fingerprint could be generated from the resolved artifacts, for example:

group:name:version

for every Compose-related dependency.

If the fingerprint changes:

old fingerprint != new fingerprint

the Preview runtime DEX should be regenerated.

If it remains unchanged, the existing DEX can be reused.

Expected result

Compose Preview should execute using the same resolved Compose/Material3 dependency versions that were used to compile the user's project.

This should prevent errors such as:

NoSuchMethodError
NoSuchFieldError
IncompatibleClassChangeError
ClassNotFoundException

caused by mismatched Compose runtime versions.

Additional consideration

The Preview compiler should also use a Compose Compiler plugin compatible with the project's Kotlin compiler.

For Kotlin 2.x, the Preview compiler should use the corresponding Kotlin Compose Compiler plugin rather than the legacy "androidx.compose.compiler:compiler"artifact.

For example:

Kotlin Compiler: 2.3.21
Compose Compiler Plugin: 2.3.21

This should be handled separately from the runtime dependency synchronization described above.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions