Skip to content

Instantly share code, notes, and snippets.

@s4cha
Last active June 20, 2019 14:58
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save s4cha/f5a387de703b82b01660eee4d142df03 to your computer and use it in GitHub Desktop.
Save s4cha/f5a387de703b82b01660eee4d142df03 to your computer and use it in GitHub Desktop.
EventBus in Kotlin under 50 lines \o/
import kotlinx.coroutines.*
typealias Callback<T> = (T) -> Unit
class CallbackWrapper<T>(val callback:Callback<T>, val eventName: String, val receiverHash: Int, val dispatcher: CoroutineDispatcher)
object Notifier: CoroutineScope {
private val supervisorJob = SupervisorJob()
override val coroutineContext = Dispatchers.Main + supervisorJob
var callbacks = mutableListOf<CallbackWrapper<Any>>()
fun post(event: Any, sender: Any) {
callbacks.filter {
it.eventName == event::class.simpleName && it.receiverHash != sender.hashCode()
}.forEach {
launch(it.dispatcher) {
it.callback.invoke(event)
}
}
}
inline fun <reified T> register(receiver: Any, token: NotifierToken = NotifierToken(), on: CoroutineDispatcher = Dispatchers.Main, noinline callback: Callback<T>) {
val wrapper = CallbackWrapper(callback, T::class.simpleName ?: "noname", receiver.hashCode(), on) as CallbackWrapper<Any>
callbacks.add(wrapper)
token.unregistrationCodes.add { callbacks.remove(wrapper) }
}
}
class NotifierToken {
var unregistrationCodes = mutableListOf<(() -> Unit)>()
fun unregister() {
unregistrationCodes.forEach { it.invoke() }
}
}
interface NotifierSubscriber {
var notifierToken: NotifierToken
fun unregisterNotifications() {
notifierToken.unregister()
}
}
inline fun <reified T>NotifierSubscriber.subscribeFor(dispatcher: CoroutineDispatcher = Dispatchers.Main, noinline callback: Callback<T>) {
Notifier.register(this, notifierToken, dispatcher, callback)
}
interface NotifierPublisher {
fun publishEvent(event: Any, from: Any = this) {
Notifier.post(event, from)
}
}
// Create your custom event.
data class NewPostEvent(val newPost: Post)
class MySubscriberFragment: Fragment(), NotifierSubscriber {
// Store a cancellation token
override var notifierToken = NotifierToken()
override fun onStart() {
super.onStart()
// Subscribe
subscribeFor<NewPostEvent>{
// do someting cool
}
}
override fun onStop() {
super.onStop()
unregisterNotifications()
}
}
class MyPublisherFragment: Fragment(), NotifierPublisher {
fun foo() {
publishEvent(NewPostEvent(myNewPost)
}
}
@Pafgz
Copy link

Pafgz commented Jun 12, 2019

What an amazing and clean code!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment