Krate

Additional

Language
Kotlin
Version
N/A
Created
Jul 8, 2018
Updated
Feb 4, 2019
Owner
Gustav Karlsson (gustavkarlsson)
Contributor
Gustav Karlsson (gustavkarlsson)
1
Activity
Badge
Generate
Download
Source code

Commercial

Krate

Krate is a predictable state container for Kotlin and RxJava. It brings order to the chaos by taking care of the data flow in your app. Krate is heavily inspired by This talk by Jake Wharton but also Flux and Redux.

Why Krate?

  • Predictable: Full control of application state changes, even during async operations
  • Asynchronous: Built with RxJava to simplify asynchronous programming
  • Unidirectional: Data flows in one direction, making it easier to reason about
  • Separation of concerns: Clear distinction between what and how
  • DSL: The initial setup is done using a fully documented developer-friendly DSL
  • Kotlin powered: Utilizes advanced Kotlin features to provide a beautiful API
  • Pluggable: Functionality can be bundled into plugins and easily added to the project
  • Great with Android: Alleviates many annoying aspects of Android development

Minimal example

Here is minimal working example that demonstrates the very basics of Krate:

import io.reactivex.Single
import se.gustavkarlsson.krate.core.dsl.buildStore
import java.util.Random
import java.util.concurrent.TimeUnit

// Define an immutable state class
data class State(val weather: String? = null)

// Define commands as a sealed class hierarchy
sealed class Command
object GetWeather : Command()

// Define results as a sealed class hierarchy
sealed class Result
data class WeatherReport(val weather: String) : Result()

// Fake async API for demonstration purposes
object WeatherApi {
    private val random = Random()

    fun getWeather(): Single<String> {
        return Single.fromCallable(::fakeWeather)
            .delay(2, TimeUnit.SECONDS)
    }

    private fun fakeWeather(): String {
        val temperature = random.nextInt(35)
        val condition = if (random.nextBoolean()) "clear" else "raining"
        return "It's $temperature° and $condition"
    }
}

// Create a store with type parameters
val store = buildStore<State, Command, Result> {

    states {
        initial = State() // An initial state must be set
    }

    commands {
        // Transform GetWeather commands to results
        transform<GetWeather> { commands ->
            commands
                .flatMapSingle {
                    WeatherApi.getWeather()  // Call API for each GetWeather command
                        .map<Result> { weather ->
                            WeatherReport(weather) // Map API response to Result
                        }
                }
        }

        watch<GetWeather> { println("GetWeather") } // Log GetWeather commands
    }

    results {
        // Update state whenever a WeatherReport arrives
        reduce { state, result ->
            when (result) {
                WeatherReport -> state.copy(weather = report.weather)
                else -> state
            }
        }
    }
}

fun main(args: Array<String>) {

    // Observe the store for state changes
    store.states.subscribe {
        // Typically the state would be rendered here
        println("$it")
    }

    // Fake some user interactions
    store.issue(GetWeather)
    Thread.sleep(1000)
    store.issue(GetWeather)
    Thread.sleep(2000)
    store.issue(GetWeather)

    Thread.sleep(10000)
}

Outputs:

State(weather=null)
GetWeather
GetWeather
State(weather=It's 11° C and raining)
GetWeather
State(weather=It's 21° C and clear)
State(weather=It's 32° C and raining)

Learn more

Check out the wiki for documentation.

You can also check out one of the provided sample projects.

Download

Krate is hosted on JitPack. Here's how you include it in your gradle project:

Step 1. Add the JitPack repository to your build file:

allprojects {
    repositories {
        // Other repositories
        maven { url 'https://jitpack.io' }
    }
}

Step 2. Add the dependency:

dependencies {
    implementation 'com.github.gustavkarlsson.krate:krate-core:<latest_version>'
}

For maven, sbt and leiningen, go to JitPack