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 emittedSuccess(value: T)
: only emitted when your code is successfully executedFailure(exception: Throwable)
: only emitted when an exception is thrownFinish
: 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
- Add the JitPack repository in your root build.gradle at the end of repositories:
allprojects {
repositories {
maven { url 'https://jitpack.io' }
}
}
- Next, add the library to your module:
dependencies {
implementation "com.github.adrielcafe:dalek:$currentVersion"
}