Skip to content

Extensions for Android views

Experimental extensions and utilities for easier integration of Decompose with Android views.


Extensions for Android views are provided by the extensions-android module.

implementation "com.arkivanov.decompose:extensions-android:<version>"


Decompose is primarily designed for better integration with declarative UI frameworks, such as Jetpack/JetBrains Compose, SwiftUI, Kotlin/React, etc. However it still can be used with Android views. Because the main Decompose functionality is separate from UI, the latter has to be plugged externally. This module provides some essential extensions and utilities to improve the experience.


As mentioned before, Decompose is not aware of any UI. Because the UI is plugged externally, it needs its own Lifecycle. The idea is to supply every view sub-tree with ViewContext, which exposes the following properties:

parent - a ViewGroup where the view sub-tree should be inflated lifecycle - a Lifecycle of the view sub-tree

The following ViewContext extensions are available:

  • val ViewContext.context: Context - returns the Android Context of the view sub-tree
  • val ViewContext.resources: Resources - returns the Android Resources of the view sub-tree
  • val ViewContext.layoutInflater: LayoutInflater - returns the Android LayoutInflater
  • fun ViewContext.child(ViewGroup, inflater): ViewContext - creates a child ViewContext with another parent ViewGroup, which shares the Lifecycle of the parent ViewContext. The inflater arguments should inflate a sub-tree of views, but without adding it to the parent.

DefaultViewContext - is a default implementation of ViewContext, which can be used to manually create new instances when needed.


StackRouterView is an Android ViewGroup which observes the Child Stack and manages child views. Once StackRouterView is added to the view hierarchy, just call its children(...) method with the following arguments:

  • stack - the observable Value of ChildStack
  • lifecycle - the lifecycle of the StackRouterView or its closest parent
  • replaceChildView - a function which replaces a currently active child view with a new one, this is also the place where transitions can be applied


You can find an example of using this extension module in the Counter sample.

Initializing the root in Activity:

import android.os.Bundle
import com.arkivanov.decompose.defaultComponentContext
import com.arkivanov.essenty.lifecycle.essentyLifecycle

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {


        val root = DefaultCounterComponent(defaultComponentContext())

        val viewContext =
                parent = findViewById(,
                lifecycle = essentyLifecycle()

        viewContext.apply {

A simple child view:

import android.view.View
import android.widget.TextView
import com.arkivanov.decompose.value.observe

fun ViewContext.CounterView(component: CounterComponent): View {
    // Inflate the layout without adding it to the parent
    val layout = layoutInflater.inflate(R.layout.counter, parent, false)

    // Find required views
    val counterText: TextView = layout.findViewById(

    // Observe Counter models and update the view
    component.model.observe(lifecycle) { data ->
        counterText.text = data.text

    return layout // Return the root of the inflated sub-tree

StackRouterView example:

import android.view.View

fun ViewContext.RootView(component: RootComponent): View {
    val layout = layoutInflater.inflate(R.layout.counter_root, parent, false)
    val nextButton: View = layout.findViewById(
    val routerView: StackRouterView = layout.findViewById(

    nextButton.setOnClickListener { counterRoot.onNextChild() }

    // Create a child `ViewContext` for the permanent `CounterView`
    child(layout.findViewById( {
        // Reuse the `CounterView`

    // Subscribe the `StackRouterView` to the `ChildStack` changes
    routerView.children(component.childStack, lifecycle) { parent, newStack, _ ->
        // Remove all existing views

        // Add the child view for the currently active child component

    return layout