GithubHelp home page GithubHelp logo

adrielcafe / broker Goto Github PK

View Code? Open in Web Editor NEW
94.0 4.0 8.0 235 KB

๐Ÿ’ฌ Publish-Subscribe (a.k.a Pub/Sub, EventBus) library for Android and JVM built with Coroutines

License: MIT License

Kotlin 100.00%
android android-library kotlin kotlin-library kotlin-android kotlin-coroutines publisher-subscriber publish-subscribe pubsub pub-sub

broker's Introduction

JitPack Android API Github Actions Codacy Codecov kotlin ktlint License MIT

Broker

Broker is a Publish-Subscribe (a.k.a Pub/Sub, EventBus) library for Android and JVM built with Coroutines.

class MyActivity : AppCompatActivity(), GlobalBroker.Subscriber {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        subscribe<MyEvent>(this) { event ->
            // Handle event
        }
    }
}

class MyViewModel : ViewModel(), GlobalBroker.Publisher {

    fun doSomething() {
        publish(MyEvent(payload))
    }
}

Features

  • Helps to decouple your code: publishers are loosely coupled to subscribers, and don't even need to know of their existence
  • Works great with Activity, Fragment, Service, Custom View, ViewModel...
  • Provides a global instance by default and lets you create your own instances
  • Also provides useful extension functions to avoid boilerplate code
  • Android Lifecycle-aware: unsubscribe to events automatically
  • Retained event: cache the last published events
  • Thread-safe: you can publish/subscribe from any thread
  • Fast: all work is done outside the main thread and the events are delivered through a Coroutines Flow
  • Small: ~30kb

Usage

Take a look at the sample app for working examples.

Creating events

Events (a.k.a Topic, Message) can be represented as object (without payload) and data class (with payload).

object EventA
data class EventB(val message: String)

You can also group your events inside a sealed class, this way you can organize events by module, feature, scope, or similar.

sealed class MyEvent {
    object EventA : MyEvent()
    data class EventB(val message: String) : MyEvent()
}

Global Pub/Sub

Broker provides a global instance by default with some useful extension functions.

Call GlobalBroker.subscribe<YourEvent>() to subscribe to an event and GlobalBroker.unsubscribe() to unsubscribe to all events.

To subscribe, you should pass as parameters:

  • The subscriber (usually the current class but can be a String, Int, object...)
  • A CoroutineScope (tip: use the built-in lifecycleScope and viewModelScope)
  • An optional CoroutineContext to run your lambda (default is Dispatchers.Main)
  • A suspend lambda used to handle the incoming events

Call subscribe() in onStart() (for Activity and Fragment) and onAttachedToWindow() (for Custom View), and call unsubscribe() in onStop() (for Activity and Fragment) and onDetachedFromWindow() (for Custom View).

class MyActivity : AppCompatActivity() {

    override fun onStart() {
        super.onStart()
        GlobalBroker.subscribe<MyEvent>(this, lifecycleScope) { event ->
            // Handle event
        }
    }

    override fun onStop() {
        GlobalBroker.unsubscribe(this)
        super.onStop()
    }
}

To publish events just call GlobalBroker.publish() passing the event as parameter. It can be called from any thread.

class MyViewModel : ViewModel() {

    fun doSomething() {
        GlobalBroker.publish(MyEvent)
    }
}

GlobalBroker.Publisher & GlobalBroker.Subscriber

You can avoid some boilerplate code by implementing the GlobalBroker.Publisher and GlobalBroker.Subscriber interfaces. This also helps to identify the role of your class: is it a Publisher or Subscriber?

class MyActivity : AppCompatActivity(), GlobalBroker.Subscriber {

    override fun onStart() {
        super.onStart()
        subscribe<MyEvent>(lifecycleScope) { event ->
            // Handle event
        }
    }

    override fun onStop() {
        unsubscribe()
        super.onStop()
    }
}

class MyViewModel : ViewModel(), GlobalBroker.Publisher {

    fun doSomething() {
        publish(MyEvent)
    }
}

Local Pub/Sub

In some situations a global instance is not a good option, because of that you can also create your own Broker instance.

In the example below, we use Koin to inject a Broker instance in the MyActivity scope.

val myModule = module {

    scope<MyActivity> {
        scoped { Broker() }

        viewModel { MyViewModel(broker = get()) }
    }
}

And now we can inject a local Broker instance:

class MyActivity : AppCompatActivity() {

    private val broker by instance<Broker>()

    override fun onStart() {
        super.onStart()
        broker.subscribe<MyEvent>(this, lifecycleScope) { event ->
            // Handle event
        }
    }

    override fun onStop() {
        broker.unsubscribe(this)
        super.onStop()
    }
}

class MyViewModel(broker: Broker) : ViewModel() {

    fun doSomething() {
        broker.publish(MyEvent)
    }
}

BrokerPublisher & BrokerSubscriber

Broker class implements two interfaces: BrokerPublisher and BrokerSubscriber. You can use this to inject only the necessary behavior into your class.

Let's back to the previous example. Instead of provide a Broker instance directly we can provide two injections, one for publishers and another for subscribers.

val myModule = module {

    scope<MyActivity> {
        val broker = Broker()

        scoped<BrokerPublisher> { broker }

        scoped<BrokerSubscriber> { broker }

        viewModel { MyViewModel(broker = get<BrokerPublisher>()) }
    }
}

Now we can inject only what our class needs:

class MyActivity : AppCompatActivity() {

    private val broker by instance<BrokerSubscriber>()
}


class MyViewModel(broker: BrokerPublisher) : ViewModel()

Android Lifecycle-aware

Broker's subscribers can be lifecycle-aware! Works for global and local instances.

Instead of subscribe in onStart() and unsubscribe in onStop() just subscribe in onCreate() and pass the lifecycleOnwer as parameter. Your events will now be automatically unsubscribed!

class MyActivity : AppCompatActivity(), GlobalBroker.Subscriber {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        subscribe<MyEvent>(owner = this) { event ->
            // Handle event
        }
    }
}

Retained Events

It's possible to retain the last published event of a given type. Every time you subscribe to a retained event it will be emitted immediately.

Just use the flags emitRetained when subscribing and retain when publishing:

subscribe<MyEvent>(this, emitRetained = true) { event ->
    // Handle event
}

publish(MyEvent, retain = true)

At any moment you can query for a retained event (will return null if there are none):

val lastEvent = getRetained<SampleEvent>()

// removeRetained() will also return the last retained event
val lastEvent = removeRetained<SampleEvent>()

Error handling

If the subscriber's lambda throws an error, Broker will catch it and publish the event BrokerExceptionEvent. Just subscribe to it if you want to handle the exceptions.

subscribe<BrokerExceptionEvent>(lifecycleScope) { event ->
    // Handle error
}

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 desired dependencies to your module:
dependencies {
    // Core
    implementation "com.github.adrielcafe.broker:broker-core:$currentVersion"

    // Android Lifecycle support
    implementation "com.github.adrielcafe.broker:broker-lifecycle:$currentVersion"
}

Current version: JitPack

Platform compatibility

broker-core broker-lifecycle
Android โœ“ โœ“
JVM โœ“

broker's People

Contributors

adrielcafe avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

broker's Issues

Own repository

Hi,

First, thanks for the great library.

As this library is a great library and a great project i suggest you put it into an own repository.

Thanks.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.