我有一个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
}
}
}
如何转换 Boolean
到 Flow<Boolean>
?
如果你认为可以有任何其他方式来订阅网络上发生的变化,请告诉我。
谢谢你的帮助和建议。
用 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
}
}
}
你所要做的就是从类外收集它的值。请记住,它是混合的,所以在它的值改变之前不会通知观察者。
myConnectionChangeReceiver.networkConnectionActivated
.collect { isNetworkConnectionActive ->
//Do something here
}
不要忘了在需要的时候停止所有的观察者 通过取消它们运行的所有coroutine来停止。
你可以找到 StateFlow
公文 此处.
Flow
应该是自带的数据流。
你只能在初始化时通过流构建器发送数据。你不能从构建器外部随机向它发出数据。
所以,对于你的目的,你可以使用 LiveData
而不是Flow。
只要创建一个 MutableLiveData<Boolean>
并将其送回 getNetworkAvailability()
.
每当网络状态发生变化时,只要调用 setValue()
有价值 postValue()
如果在后台线程中)发送最新状态。
并在另一边用 networkLiveData.observe()
并使用这些变化来做一些事情。
除了LiveData,你还可以使用ConflatedBroadcastChannel。
希望能帮到你。
我想你需要一个 Channel
,然后你可以把它转换为一个 Flow
使用扩展函数 receiveAsFlow
和 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()
}