如何在Kotlin Coroutines中把Flow<Boolean>从Boolean转换过来?

问题描述 投票:0回答:1

我有一个Android库,在这个库中,我正在监听网络变化,我想做的是,使用coroutines的Flowlaunch观察这些变化。

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

我已经采取了一个变量 isNetworkConnectionActive 上设置为假。init 的库,并在下面的函数中根据网络变化设置为真假。

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()
    }
}

现在,我想听一听发生在 isNetworkConnectionActive 变量,使用 Flow****这里我有一个类型错误,我想返回BOOLEAN的流量,但但我返回BOOLEAN.***。

  fun getNetworkAvailability(): Flow<Boolean> {

        return OfflineDataLibrary.isNetworkConnectionActive
    }

我可以访问上面的功能,并像这样监听变化。

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

如何转换 BooleanFlow<Boolean>?

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

谢谢你的帮助和建议。

android kotlin kotlin-coroutines flow kotlin-coroutines-flow
1个回答
3
投票

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
        }
    }
}

你所要做的就是从类外收集它的值。请记住,它是混合的,所以在它的值改变之前不会通知观察者。

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

不要忘了在需要的时候停止所有的观察者 通过取消它们运行的所有coroutine来停止。

你可以找到 StateFlow 公文 此处.


1
投票

Flow 应该是自带的数据流。

你只能在初始化时通过流构建器发送数据。你不能从构建器外部随机向它发出数据。

所以,对于你的目的,你可以使用 LiveData 而不是Flow。

只要创建一个 MutableLiveData<Boolean> 并将其送回 getNetworkAvailability().

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

并在另一边用 networkLiveData.observe() 并使用这些变化来做一些事情。

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

希望能帮到你。


0
投票

我想你需要一个 Channel,然后你可以把它转换为一个 Flow 使用扩展函数 receiveAsFlowconsumeAsFlow 在写这个答案的时候,它是一个实验性的功能)。所以抽象的说,你的代码会是这样的。

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()
}
© www.soinside.com 2019 - 2024. All rights reserved.