如何从 Kotlin 协同程序中的布尔值 return/convert 流<Boolean>?

How to return/convert Flow<Boolean> from Boolean in Kotlin Coroutines?

我有一个 Android 库,我在其中监听网络变化,我想做的是,使用协程Flow/launch观察这些变化

这是我的 NetworkReceiver,当连接发生变化时它会通知我

我使用了一个变量 isNetworkConnectionActive,它在库的 init 上设置为 false,并根据网络变化在下面的函数中设置为 true false

class ConnectionChangeReceiver: BroadcastReceiver() {
    override fun onReceive(context: Context?, p1: Intent?) {
        if(isNetworkConnectionActive(context)) {
            OfflineDataLibrary.isNetworkConnectionActive = true
            Toast.makeText(context, "isNetworkConnectionActive - YES", Toast.LENGTH_LONG).show()
        } else {
            OfflineDataLibrary.isNetworkConnectionActive = false
            Toast.makeText(context, "isNetworkConnectionActive - NO", Toast.LENGTH_LONG).show()
        }

    }

    fun isNetworkConnectionActive(context: Context?): Boolean {
        val connectivityManager: ConnectivityManager = context?.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
        var isConnectionActive = false
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            val nw      = connectivityManager.activeNetwork ?: return false
            val actNw = connectivityManager.getNetworkCapabilities(nw) ?: return false
            return when {
                actNw.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true
                actNw.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true
                else -> false
            }
        } else {
            val nwInfo = connectivityManager.activeNetworkInfo ?: return false
            return nwInfo.isConnected
        }
    }
}

OfflineDataLibrary 其中有 isNetworkConnectionActive

object OfflineDataLibrary {
    lateinit var context: Context
    var isNetworkConnectionActive: Boolean = false
    fun init(ctx: Context) {
        context = ctx.applicationContext
        val offlineDataChangeListener = OfflineDataChangeListener()
        offlineDataChangeListener.observeOfflineDataChanges()
    }
}

现在我想使用 Flow 监听 isNetworkConnectionActive 变量发生的变化 *这里我有一个类型不匹配,我想 RETURN 布尔值流但我是 RETURNING 布尔值。

  fun getNetworkAvailability(): Flow<Boolean> {

        return OfflineDataLibrary.isNetworkConnectionActive
    }

我可以访问上面的函数并听取这样的变化

  fun getIsNetworkAvailable() {
        launch {
        OfflineDatabaseManager.getInstance(app.applicationContext).getNetworkAvailability().collect {
                //DO something
            }
        }
    }

如何将 Boolean 转换为 Flow<Boolean>

如果您认为可以通过任何其他方式订阅网络上发生的变化,请告诉我。

Flow 应该是独立的数据流。

您只能在初始化时通过流生成器发送数据。您不能从构建器外部随机向其发送数据。

因此,为了您的目的,您可以使用 LiveData 而不是 Flow。

只需在 getNetworkAvailability().

中创建 MutableLiveData<Boolean> 和 return 的实例

每当网络状态发生变化时,只需调用 setValue() 和值(如果在后台线程中,则调用 postValue())以发送最新状态。

另一方面,使用 networkLiveData.observe() 观察变化并使用这些变化来做事。

除了LiveData,您还可以使用ConflatedBroadcastChannel。

希望对您有所帮助。

我认为您需要 Channel, then you can convert it to a Flow using extension functions receiveAsFlow and consumeAsFlow(在撰写此答案时它是一项实验性功能)。因此,以抽象的方式,您的代码如下所示:

class YouClass {
    private val networkConnectionChannel : Channel<Boolean>(Channel.CONFLATED)

    var isNetworkConnected: Boolean
    get
    set {
        field = value
        networkConnectionChannel.sendBlocking(value)
    }

    fun getNetworkConnectionFlow() : Flow<Boolean> =
        networkConnectionChannel.receiveAsFlow()
}

使用 StateFlow,您不必使用 LiveDataConflatedChannel,甚至不必将 Channel 转换为 Flow:

class ConnectionChangeReceiver: BroadcastReceiver() {

    private val _networkConnectionActivated = MutableStateFlow(false) //An initial value is required
    val networkConnectionActivated: StateFlow<Boolean>
        get() = _networkConnectionActivated

    override fun onReceive(context: Context?, p1: Intent?) {
        _networkConnectionActivated.value = isNetworkConnectionActive(context)
    }

    fun isNetworkConnectionActive(context: Context?): Boolean {
        val connectivityManager: ConnectivityManager = context?.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
        var isConnectionActive = false
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            val nw      = connectivityManager.activeNetwork ?: return false
            val actNw = connectivityManager.getNetworkCapabilities(nw) ?: return false
            return when {
                actNw.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true
                actNw.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true
                else -> false
            }
        } else {
            val nwInfo = connectivityManager.activeNetworkInfo ?: return false
            return nwInfo.isConnected
        }
    }
}

您所要做的就是从 class 外部收集它的值。请记住它是合并的,因此在其值更改之前不会通知观察者:

myConnectionChangeReceiver.networkConnectionActivated
    .collect {  isNetworkConnectionActive ->
        //Do something here
    }

不要忘记在需要时通过取消所有 运行 上的协程来停止所有观察者。

您可以找到 StateFlow 官方文档 here