繁体   English   中英

如何返回/转换 Flow<boolean> 从 Boolean 到 Kotlin 协程?</boolean>

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

我有一个 Android 库,我正在其中收听网络变化,我想做的是,使用协同程序的流程/启动观察这些变化

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

我采用了一个变量isNetworkConnectionActive ,它在库的init时设置为 false,并根据 .network 更改在下面的 function 中设置为 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
        }
    }
}

具有 isNetworkConnectionActive 的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变量发生的变化 *这里我有一个类型不匹配,我想返回 BOOLEAN 的流量,但我正在返回 BOOLEAN。

  fun getNetworkAvailability(): Flow<Boolean> {

        return OfflineDataLibrary.isNetworkConnectionActive
    }

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

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

如何将Boolean转换为Flow<Boolean>

如果您认为可以通过任何其他方式订阅 .network 上发生的更改,请告诉我。

使用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官方文档。

Flow应该是自包含stream的数据。

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

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

只需创建一个MutableLiveData<Boolean>的实例并将其返回到getNetworkAvailability()中。

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

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

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

希望能帮助到你。

我认为您需要一个Channel ,然后您可以使用扩展函数receiveAsFlowconsumeAsFlow将其转换为Flow (在撰写此答案时,它是一项实验性功能)。 因此,以抽象的方式,您的代码如下所示:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM