[go: up one dir, main page]

Skip to content

🤖 UI driven state machine for Android & JVM that will exterminate your bugs

License

Notifications You must be signed in to change notification settings

adrielcafe/dalek

Repository files navigation

Banner

JitPack Github Actions Android API Kotlin ktlint License MIT

Dalek

Dalek is a tiny (~10 LOC) finite state machine that helps you manage the UI state of your app when running async/breakable tasks.

It's powered by Coroutines Flow and works on Android & JVM.

Why Dalek?

Daleks are a fictional extraterrestrial race of mutants portrayed in Doctor Who.

They are creatures that live inside a tank-like robotic shell, and this is basically how this library works: your code (the "creature") is wrapped and executed inside a state machine (the "robotic shell").

"EXTERMINATE! EXTERMINATE! EXTERMINATE!"
(Any Dalek will say that)

Motivation

Let's imagine the following scenario: you need to retrieve a Post object from a REST API, something like:

class PostRepository {

    suspend fun getPost(id: String): Post {
        // async api call
        // serialization
        // error handling
    }
}

It's an asynchronous operation that can take a while to complete and can fail (TimeoutException, IOException, SerializationException...). But wait, there's more: you need to keep the UI updated so your user knows what's going on.

This is a nightmare, right? Calm down! Dalek is here to help 🤖

Usage

1. Wrap your code inside Dalek

To start using Dalek, you just need to wrap your existing code inside it.

Dalek will run your code inside a suspend fun and return a Flow<DalekEvent<T>>, where T is the output of your code (you can return null, Unit and Any, I won't judge you).

class MyViewModel(private val repository: PostRepository) : ViewModel() {

    fun getPost(id: String): Flow<DalekEvent<Post>> =
        Dalek(Dispatchers.IO) {
            repository.getPost(id)
        }
}

2. Handle the UI events

Dalek will emit the following events:

  • Start: always emitted
  • Success(value: T): only emitted when your code is successfully executed
  • Failure(exception: Throwable): only emitted when an exception is thrown
  • Finish: always emitted
class MyActivity : AppCompatActivity() {

    private fun loadPost(id: String) {
        viewModel.getPost(id)
            .collectIn(lifecycleScope) { event ->
                when (event) {
                    is Start -> setLoading(true)
                    is Success -> showPost(event.value)
                    is Failure -> showError(event.exception)
                    is Finish -> setLoading(false)
                }
            }
    }
}

Import to your project

  1. Add the JitPack repository in your root build.gradle at the end of repositories:
allprojects {
    repositories {
        maven { url 'https://jitpack.io' }
    }
}
  1. Next, add the library to your module:
dependencies {
    implementation "com.github.adrielcafe:dalek:$currentVersion"
}

Current version: JitPack