u/Educational_Hall_249

Image 1 — Hikage - A real-time Android View runtime powered by Kotlin DSL
Image 2 — Hikage - A real-time Android View runtime powered by Kotlin DSL
Image 3 — Hikage - A real-time Android View runtime powered by Kotlin DSL
▲ 16 r/Kotlin+1 crossposts

Hikage - A real-time Android View runtime powered by Kotlin DSL

I have been writing Android long enough to feel the strange split in the UI world.

On one side, XML is boring in the best and worst ways. It is stable, deeply integrated with the platform, understood by every legacy custom View, and still works with the Android pipeline that has existed for years. On the other side, Jetpack Compose gives Kotlin developers a much better authoring model: UI as code, local composition, reusable functions, less ceremony.

But real projects are rarely clean rewrites.

A lot of Android apps still live in the View ecosystem. They have custom Views, AppCompat behavior, Material components, LayoutInflater.Factory2, old XML attributes, obtainStyledAttributes, ViewBinding, and code that cannot simply be deleted because a newer UI framework exists.

I wanted something in the middle.

Not "replace Compose". Not "keep writing XML forever". Something closer to: what if the classic Android View system could be authored like modern Kotlin code?

That became Hikage.

Hikage is a real-time Android View runtime powered by Kotlin DSL. Crucially, Hikage doesn't reinvent the wheel with a new UI component system. It acts as a transporter for the existing Android View ecosystem. It is more like a transporter for the existing Android View ecosystem.

A simple layout looks like this:

LinearLayout(
    lparams = LayoutParams(matchParent = true),
    init = {
        orientation = LinearLayout.VERTICAL
        gravity = Gravity.CENTER
    }
) {
    TextView {
        text = "Hello, World!"
        textSize = 16f
        gravity = Gravity.CENTER
    }
}

That part is nice, but honestly, syntax alone is not the interesting bit. Android has already had DSL attempts before. Anko existed. Splitties exists. Compose exists.

The part I cared about was whether a Kotlin DSL could still behave like a first-class citizen in the old View world.

For example, Hikage can mix with existing layouts instead of forcing a rewrite:

LinearLayout(
    lparams = LayoutParams(matchParent = true),
    init = {
        orientation = LinearLayout.VERTICAL
    }
) {
    Layout(R.layout.my_layout)
    Layout<MyLayoutBinding>()

    ComposeView {
        Text("Hello from Compose")
    }
}

And the bridge goes both directions: Hikage can host Compose, and Compose can host Hikage.

The bigger technical problem was XML attributes.

A lot of real Android Views are not designed to be fully configured by setters. They expect values in the constructor through AttributeSet, then call obtainStyledAttributes. XML gets this naturally because AAPT2 compiles the layout and LayoutInflater feeds the resulting parser into View(Context, AttributeSet).

A normal Kotlin DSL usually skips that path.

Hikage tries to enter it.

It can dynamically construct an AttributeSet at runtime, so this:

TextView(
    attrs = {
        android {
            set("text", "Set text in dynamic AttributeSet")
            set("textSize", "16sp")
            set("gravity", "center")
            set("paddingLeft", "8dp")
            set("paddingRight", 8.dp)
        }
    }
) {
    text = "Overridden text in code"
}

is not just setting properties after construction. It lets the View receive XML-style attributes during creation.

Internally, the runtime builds an in-memory XML-like structure, resolves attributes, separates layout_* attributes for parent LayoutParams, and then lets the View constructor / factory chain do what Android Views already know how to do.

The architecture is roughly:

Kotlin DSL
 -> LayoutSession
 -> optional runtime AttributeSet resolver
 -> HikageFactory / LayoutInflater.Factory2 bridge
 -> View(Context, AttributeSet)
 -> init block
 -> parent LayoutParams
 -> View tree

For traditional XML, the comparable path is:

XML layout
 -> AAPT2 compiled XML
 -> LayoutInflater
 -> XmlResourceParser / AttributeSet
 -> Factory2 / AppCompat interception
 -> View(Context, AttributeSet)
 -> View tree

That is the design idea: not bypassing the old platform, but meeting it where it already works.

There are some practical pieces around it too:

  • KSP can generate DSL functions for custom Views and third-party Views.
  • Declaration JSON files can describe external View components.
  • AndroidX and Material View declarations are provided as modules.
  • Android Studio preview is supported through a HikagePreview View.
  • There is lightweight state binding for View-based layouts. State changes mutate existing View instances instead of rebuilding the whole tree.
  • It can work with XML, ViewBinding, Compose, and plain Views in the same layout.
  • The runtime attribute module has been tested across Android 5.0.2 / API 21 through Android 17 / API 37 on emulators and real devices.

I do not want to oversell benchmarks, because that is not the main point. The main point is the architecture. The benchmark and compatibility reports are there so people can verify the claim instead of taking my word for it.

There are also tradeoffs.

The runtime XML attribute module uses reflection around XmlBlock, so if you ship to Google Play, you should evaluate that risk carefully. Hikage keeps it as a separate runtime extension instead of making it mandatory. If you only need the DSL layout runtime, you can use the core pieces without that module.

I built this because I think Android UI does not have to be a binary choice between "old XML forever" and "rewrite everything in Compose".

The View ecosystem is still huge. Compose is important. XML is still everywhere. There should be a middle state for teams that want Kotlin authoring, runtime layout construction, and compatibility with the Views they already have.

That middle state is what Hikage is trying to be.

GitHub: https://github.com/BetterAndroid/Hikage
Docs: https://betterandroid.github.io/Hikage/en
Architecture notes: https://betterandroid.github.io/Hikage/en/guide/architecture

I would be especially interested in feedback from people who maintain mixed View / Compose apps, custom View libraries, or large legacy Android codebases. The question I keep coming back to is: if View-based Android is not going away tomorrow, what should its modern authoring layer look like?

u/Educational_Hall_249 — 14 hours ago