![](/img/trans.png)
[英]How to return fusedLocationProviderClient().lastLocation as flow from a function in kotlin coroutines
[英]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
,您不必使用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
官方文档。
Flow
应该是自包含stream的数据。
您只能在初始化时通过流构建器发送数据。 您不能从构建器外部随机向其发送数据。
因此,为了您的目的,您可以使用LiveData
而不是 Flow。
只需创建一个MutableLiveData<Boolean>
的实例并将其返回到getNetworkAvailability()
中。
每当网络 state 发生变化时,只需调用带有值的setValue()
(如果在后台线程中,则调用postValue()
)以发送最新的 state。
另一方面,使用networkLiveData.observe()
观察变化并使用变化来做事。
除了 LiveData,您还可以使用 ConflatedBroadcastChannel。
希望能帮助到你。
我认为您需要一个Channel
,然后您可以使用扩展函数receiveAsFlow
和consumeAsFlow
将其转换为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.