如何从 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
,您不必使用 LiveData
或 ConflatedChannel
,甚至不必将 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。
我有一个 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
,您不必使用 LiveData
或 ConflatedChannel
,甚至不必将 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。