Skip to content

Instantly share code, notes, and snippets.

@gpeal
Last active August 30, 2024 08:41
Show Gist options
  • Save gpeal/1c86aa3aacc1c26724e0d76f0023594e to your computer and use it in GitHub Desktop.
Save gpeal/1c86aa3aacc1c26724e0d76f0023594e to your computer and use it in GitHub Desktop.
Coroutine Broadcast Receivers
context.registerReceiverInScope(scope, WifiManager.WIFI_STATE_CHANGED_ACTION) { intent ->
val state = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_DISABLED)
// Use wifi state here
}
/**
* Register a broadcast receiver in the given coroutine scope for any of the specified actions
* and call the callback when it is invoked.
*/
fun Context.registerReceiverInScope(
scope: CoroutineScope,
vararg intentFilterActions: String,
callback: (Intent) -> Unit,
) {
val receiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
callback(intent)
}
}
val intentFilter = IntentFilter()
intentFilterActions.forEach { intentFilter.addAction(it) }
registerReceiver(receiver, intentFilter)
scope.invokeOnCompletion {
unregisterReceiver(receiver)
}
}
@ursusursus
Copy link

This would be nicer as a flow. Also passing coroutine scope makes it seems its somehow coroutine related, which it is not, just used to unsubscriber

@gpeal
Copy link
Author

gpeal commented Mar 27, 2021

@ursusursus funny enough, we added this recently as well:

fun Context.registerReceiverAsFlow(
    vararg intentFilterActions: String,
): Flow<Intent> = callbackFlow<Intent> {
    val receiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent) {
            sendBlocking(intent)
        }
    }
    val intentFilter = IntentFilter()
    intentFilterActions.forEach { intentFilter.addAction(it) }
    registerReceiver(receiver, intentFilter)
    awaitClose {
        unregisterReceiver(receiver)
    }
}.buffer(capacity = Channel.UNLIMITED)

@ursusursus
Copy link

great minds think alike lol

@arunm1407
Copy link

class EventBus private constructor(val scope: CoroutineScope) {

private val _bus = MutableSharedFlow<T>(replay = 1)
val bus: SharedFlow<T> = _bus.asSharedFlow()

fun post(event: T) {
    scope.launch(Dispatchers.IO) {
        _bus.emit(event)
    }
}

inline fun <reified E : T> subscribe(
    dispatcher: CoroutineDispatcher = Dispatchers.Main,
    crossinline action: (event: E) -> Unit
): Job {
    val job = SupervisorJob(scope.coroutineContext[Job])

    return scope.launch(dispatcher + job) {
        bus.filterIsInstance<E>().collect {
            action(it)
        }
    }
}

companion object {
    private lateinit var instance: EventBus<*>

    fun <T> initialize(scope: CoroutineScope): EventBus<T> {
        instance = EventBus<T>(scope)
        return instance as EventBus<T>
    }

    @Suppress("UNCHECKED_CAST")
    fun <T> get(): EventBus<T> = instance as EventBus<T>
}

}

will this code opt this ?

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