Skip to content
A declarative UI Framework for android using Kotlin
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.
.idea Ignore random Timber lint warnings although Timber is not in the proj… Feb 6, 2018
gradle/wrapper Publish to bintray Feb 5, 2018
konduit Prevent TextView from being updated when the widget was rendered befo… Aug 30, 2018
sample Add tests Feb 26, 2018
.gitignore Initial commit Feb 5, 2018
LICENSE.txt Initial commit Feb 5, 2018 Add samples Feb 26, 2018
build.gradle Publish to bintray Feb 5, 2018 Initial commit Feb 5, 2018
gradlew Make tests work in sample package Feb 5, 2018
gradlew.bat Make tests work in sample package Feb 5, 2018


Konduit - make Android Views fun again

Konduit - is a React inspired way to bind data to Android Views

Konduit is a layer on top of MVP where a Presenter talks to a View interface. Instead of calling the View interface directly you declare your UI using Widgets and Konduit will inform the View about changes automatically.

In traditional MVP implementations you have to update the View when

  • data changes (partially for each change) or
  • a new View attaches (orientation change). Having two implementations is hard to maintain and it's nothing new that mutation is the main cause of many problems.

Widgets are immutable data objects which describe the state of a View and provides listeners for user interactions. Each Widget will be bound to the corresponding Android View, a 1:1 mapping. The immutability of the Widgets allows clever diffing and reduces unnecessary updates of the Views.

Instead of calling the View directly you have to implement the build() function which should return a collection of Widgets describing your UI state. The build() function will be automatically called by Konduit when you change the state by calling setState { }. You don't have to worry anymore if your view is currently detached (view == null) causing NullPointerExceptions.

override fun build(context: BuildContext): List<Widget> {
    return widgetList {
        text {
            key =
            text = "Clicked $count times"

        button {
            key =
            text = if (count == 0) "Click me" else "Increment"
            onClick = onButtonClicked

When Konduit detects changes compared to the previous Widgets it will inform the View by calling the single render(List<Widget>) method. This method receives all Widgets at once which is crucial for testing (see later). Konduit then performs a second diff per Widget and binds changed properties to the correct Android View.


The main goal of Konduit was to ease testing. Espresso testing is great, but it requires an Android Emulator. This makes testing slow and flaky.

Konduit allows you write espresso like tests on the JVM.

    fun `button click increments`() {
        val ui = MainPresenter().testUi()

        // Given the UI shows the initial state

        // When clicking the increment button

        // Then the counter will be incremented by 1


//TODO add more details


One of the goals of MVP is the separation from the untestable Android Framework allowing us to write JVM test. When it comes to i18n this can be hard to achieve.



repositories {

dependencies {
    compile 'com.pascalwelsch.konduit:konduit:0.3.0'


See samples

  • EditText - Two-way binding of an EditText and i18n
  • Alert - Custom Widget and dynamic View
  • RecyclerView - ListsWidget with click listener bound to custom RecyclerView.Adapter
  • Options Menu - Options menu with Widgets / manual binding


Copyright 2018 Pascal Welsch

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
See the License for the specific language governing permissions and
limitations under the License.
You can’t perform that action at this time.