Mobile Development 15 min read

Migrating from Kotlin Android Extensions to Kace: A Seamless Migration Guide

This article explains why the Kotlin Android Extensions plugin is deprecated, outlines migration strategies for legacy code, introduces the open‑source Kace framework as a seamless replacement, and provides detailed setup, code generation, performance optimizations, and incremental compilation techniques for Android projects.

Yuanfudao Tech
Yuanfudao Tech
Yuanfudao Tech
Migrating from Kotlin Android Extensions to Kace: A Seamless Migration Guide

Introduction

The Kotlin Android Extensions (KAE) plugin was announced deprecated in 2020 and will be removed in Kotlin 1.8, so projects upgrading to Kotlin 1.8 must eliminate KAE.

Migration Options

The official recommendation is to migrate old projects to ViewBinding or Jetpack Compose. For large legacy codebases that heavily use KAE, manual migration is costly and error‑prone.

Legacy Code Migration Strategies

Three main approaches exist: manual modification (high cost, risk of bugs), extracting KAE into a separate module (high maintenance due to deep compiler‑plugin dependencies), and the third approach—using Kace.

What Is Kace?

Kace (kotlin-android-compatible-extensions) is an open‑source framework that helps migrate from KAE seamlessly. Repository: https://github.com/kanyun-inc/Kace .

Key advantages:

Easy integration without manual code changes.

Behavior identical to KAE (viewId caching and automatic cleanup).

Unified migration that simplifies regression testing.

Low maintenance by generating source code.

Quick Migration Steps

1. Add the plugin to the classpath

// Method 1 – traditional way in root build.gradle.kts
buildscript {
    repositories { mavenCentral() }
    dependencies { classpath("com.kanyun.kace:kace-gradle-plugin:1.0.0") }
}

 // Method 2 – new way in settings.gradle.kts
pluginManagement {
    repositories { mavenCentral() }
    plugins {
        id("com.kanyun.kace") version "1.0.0" apply false
    }
}

2. Apply the plugin

Remove the kotlin-android-extensions plugin and add:

plugins {
    id("com.kanyun.kace")
    id("kotlin-parcelize") // optional if @Parcelize is used
}

3. (Optional) Configure the plugin

By default Kace parses every layout. You can whitelist or blacklist specific layouts:

kace {
    whiteList = listOf() // only layouts in this list will be processed
    blackList = listOf("activity_main.xml") // these layouts will be ignored
}

After these steps the migration is complete.

Supported Types

Kace currently supports the four most common view types (Activity, Fragment, View, and synthetic extensions). Less‑used types such as android.app.Fragment or LayoutContainer are not yet supported.

Version Compatibility

Kotlin

AGP

Gradle

Minimum supported version

1.7.0

4.2.0

6.7.1

Kace targets Kotlin 1.8, so the minimum Kotlin version is relatively high.

Prerequisite Knowledge: Compiler Plugins

What Is a Compiler Plugin?

Kotlin compiler plugins hook into the compilation process, allowing custom logic to modify the generated bytecode or IR. They can be Gradle plugins, compiler plugins, or IDE plugins.

How KAE Works

KAE consists of several components: AndroidExtensionsSubpluginIndicator (entry point), AndroidSubplugin (parameter configuration), AndroidCommandLineProcessor (receives parameters), and AndroidComponentRegistrar (registers extensions). It converts view IDs into cached findViewByIdCached calls and clears the cache on activity destruction.

Kace Implementation

First Attempt

Generated synthetic properties for each layout, e.g.:

val AndroidExtensions.button1 get() = findViewByIdCached<Button>(R.id.button1)
class MainActivity : AppCompatActivity(), AndroidExtensions {
    private val androidExtensionImpl by lazy { AndroidExtensionsImpl() }
    override fun
findViewByIdCached(owner: AndroidExtensionsBase, id: Int): T {
        return androidExtensionImpl.findViewByIdCached(id)
    }
}

This required a lot of boilerplate per activity.

Second Attempt

Used delegation to reduce boilerplate:

private inline val AndroidExtensions.button1 get() = findViewByIdCached<Button>(this, R.id.button1)
class MainActivity : AppCompatActivity(), AndroidExtensions by AndroidExtensionsImpl() {
    override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) }
}

Still not fully seamless for hundreds of screens.

Third Attempt – Final Kace Design

Kace combines a Gradle plugin (kace-gradle-plugin) that parses XML layouts and a compiler plugin (kace-compiler) that injects the AndroidExtensions interface and its implementation into Activities/Fragments.

Key components:

KaceSyntheticResolveExtension – adds the interface.

KaceIrGenerationExtension – generates the implementation.

Generated code example:

class MainActivity : AppCompatActivity(), AndroidExtensions {
    private val $$androidExtensionImpl by lazy { AndroidExtensionsImpl() }
    override fun
findViewByIdCached(owner: AndroidExtensionsBase, id: Int): T {
        return $$androidExtensionImpl.findViewByIdCached(id)
    }
}

Kace Performance Optimizations

Explicit Input/Output

The KaceGenerateTask declares its inputs (layout XML files) and outputs (generated source) using Gradle annotations, allowing up‑to‑date checks to skip unnecessary work.

Parallel Task Execution

Each layout file is processed independently via the Gradle Worker API, turning the task into a set of parallel actions. In a module with 500 layouts, full compilation dropped from ~4 s to ~2 s.

Incremental Compilation

By marking the layout collection with @Incremental and handling InputChanges , only modified or added layouts are re‑processed, reducing incremental compile time to around 8 ms for a single layout change.

Conclusion

The article demonstrates how to adopt Kace for a painless migration from KAE, explains its internal architecture, and shows practical performance tricks such as up‑to‑date checks, parallel execution, and incremental compilation.

Open‑Source Repository

https://github.com/kanyun-inc/Kace

migrationperformanceAndroidGradleKotlinCompiler PluginKace
Yuanfudao Tech
Written by

Yuanfudao Tech

Official Yuanfudao technology account, using tech to empower education development.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.