Skip to content

Instantly share code, notes, and snippets.

@abdalin
Last active June 9, 2021 09:54
Show Gist options
  • Save abdalin/d0419411d70be264af953de9ba4e670c to your computer and use it in GitHub Desktop.
Save abdalin/d0419411d70be264af953de9ba4e670c to your computer and use it in GitHub Desktop.
A wrapper for one shot use data representing an event. The consumers of this event can provide a scope to let each consumer consume it only once
open class Event<out T>(private val data: T) {
/**
* Collection of distinct scopes this [Event] has been consumed with
*/
private val consumedScopes by lazy { hashSetOf<String>() }
/**
* Checks if this [Event] is consumed for the given scope
*/
fun isConsumed(scope: String = "") = scope in consumedScopes
/**
* Returns the data in this [Event] if it is not consumed or `null`
* Also consumes the scope if not yet consumed
* @param scope of type [String] for identifying the consumer of this [Event]
*/
fun consume(scope: String = ""): T? {
return data.takeIf { !isConsumed(scope) }?.also { consumedScopes.add(scope) }
}
/**
* Returns the data, without consuming it.
*/
fun peek(): T? = data
}
/**
* An event class that does not contain any data
*/
class NoDataEvent : Event<Unit>(Unit)
/**
* An event class for passing message events of [CharSequence] type
*/
class MessageEvent(message: CharSequence) : Event<CharSequence>(message)
/**
* kotlin extension function for [LiveData]<[Event]>
* The [Observer] is called for each scope exactly once
*/
fun <T, E : Event<T>> LiveData<E>.observeEvent(
lifecycleOwner: LifecycleOwner,
scope: String = "",
observer: Observer<T>
) {
observe(lifecycleOwner) { event ->
event?.consume(scope)?.let { observer.onChanged(it) }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment