Home > Software design >  Is it possible to stop the flow 's collection from collect's code block?
Is it possible to stop the flow 's collection from collect's code block?

Time:01-02

I am a newbie in coroutine/flow and would like to know the appropriate way to close the flow from the collect's code block when it gets the value it wanted.

The code like this:

suspend fun findService(scope:CoroutineScope, context:Context, name:String) {
  val flow = getWifiDebuggingConnectDiscoveryFlow( context )
  try {
    flow.collect {
      if(name == it.serviceName)  {
        /* need to exit the collection and execute the code that follows */
      }
    }
    println("service found!")
  } catch(e: Throwable) {
    println("Exception from the flow: $e")
  }

  /* need to do something after service found */

}

private fun getWifiDebuggingConnectDiscoveryFlow(context:Context) = callbackFlow {
  val nsdManager:NsdManager = context.getSystemService(Context.NSD_SERVICE) as NsdManager
  val listener = object : NsdManager.DiscoveryListener {
    override fun onStartDiscoveryFailed(serviceType: String?, errorCode: Int) {cancel("onStartDiscoveryFailed")}
    override fun onStopDiscoveryFailed(serviceType: String?, errorCode: Int) {cancel("onStopDiscoveryFailed")}
    override fun onDiscoveryStarted(serviceType: String?) {}
    override fun onDiscoveryStopped(serviceType: String?) {}
    override fun onServiceLost(serviceInfo: NsdServiceInfo?) {}

    override fun onServiceFound(serviceInfo: NsdServiceInfo?) {
      if(serviceInfo==null) return
      trySend(serviceInfo)
    }
  }
  nsdManager.discoverServices(ServiceDiscovery.ADB_CONNECT_TYPE, NsdManager.PROTOCOL_DNS_SD, listener)
  awaitClose { nsdManager.stopServiceDiscovery(listener) }
}

This problem has been bothering me for a long time, and I would appreciate any help I get.

CodePudding user response:

You can use the first or firstOrNull operators. It will stop collecting as soon as the first element that complies the condition is received:

val service = flow.firstOrNull { name == it.serviceName }
    ...

You can find first official documentation here

  • Related