Jetpack Compose:在ViewModel中存储并监听网络连接状态
解决网络状态监听与ViewModel状态更新问题
需求1:在ViewModel的init中启动网络监听
首先NetworkStatusViewModel需要持有ConnectivityObserver实例,推荐使用Application Context创建NetworkConnectivityObserver(避免内存泄漏),然后在init块中启动Flow收集逻辑:
修改后的ViewModel代码
class NetworkStatusViewModel( private val connectivityObserver: ConnectivityObserver ) : ViewModel() { var connectedToInternet: Boolean by mutableStateOf(false) private set // 限制外部修改,仅内部更新状态 init { // 启动网络状态监听 observeNetworkStatus() } private fun observeNetworkStatus() { viewModelScope.launch { connectivityObserver.observe().collect { status -> // 根据状态更新connectedToInternet connectedToInternet = when(status) { ConnectivityObserver.Status.Available -> true ConnectivityObserver.Status.Unavailable, ConnectivityObserver.Status.Losing, ConnectivityObserver.Status.Lost -> false } } } } }
提供ConnectivityObserver实例
在Activity/Fragment中创建ViewModel时,传入NetworkConnectivityObserver(使用Application Context):
// 在Activity中 val viewModel = ViewModelProvider(this, object : ViewModelProvider.Factory { override fun <T : ViewModel> create(modelClass: Class<T>): T { val connectivityObserver = NetworkConnectivityObserver(applicationContext) return NetworkStatusViewModel(connectivityObserver) as T } })[NetworkStatusViewModel::class.java]
如果使用Hilt等依赖注入框架,可直接将ConnectivityObserver注入ViewModel,实现更简洁的依赖管理。
需求2:网络状态变化时自动更新ViewModel状态
上面的observeNetworkStatus方法已实现该逻辑:通过collect监听ConnectivityObserver返回的Flow,每当网络状态变化时,会自动进入collect的lambda块,更新connectedToInternet这个mutableStateOf变量——由于mutableStateOf是Jetpack Compose的可观察状态,UI会自动响应状态变化。
优化原NetworkConnectivityObserver细节
原代码中send调用可简化为trySend(无需额外启动协程,更符合callbackFlow使用规范):
override fun onAvailable(network: Network) { super.onAvailable(network) trySend(ConnectivityObserver.Status.Available) } override fun onLosing(network: Network, maxMsToLive: Int) { super.onLosing(network, maxMsToLive) trySend(ConnectivityObserver.Status.Losing) } override fun onLost(network: Network) { super.onLost(network) trySend(ConnectivityObserver.Status.Lost) } override fun onUnavailable() { super.onUnavailable() trySend(ConnectivityObserver.Status.Unavailable) }
移除无用代码
原代码中的checkNetworkConnection函数可删除,因为Flow会自动发射初始网络状态,无需单独同步检查。
完整整合代码
interface ConnectivityObserver { fun observe(): Flow<Status> enum class Status { Available, Unavailable, Losing, Lost } } class NetworkConnectivityObserver(private val context: Context) : ConnectivityObserver { private val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager override fun observe(): Flow<ConnectivityObserver.Status> { return callbackFlow { val callback = object : ConnectivityManager.NetworkCallback() { override fun onAvailable(network: Network) { super.onAvailable(network) trySend(ConnectivityObserver.Status.Available) } override fun onLosing(network: Network, maxMsToLive: Int) { super.onLosing(network, maxMsToLive) trySend(ConnectivityObserver.Status.Losing) } override fun onLost(network: Network) { super.onLost(network) trySend(ConnectivityObserver.Status.Lost) } override fun onUnavailable() { super.onUnavailable() trySend(ConnectivityObserver.Status.Unavailable) } } connectivityManager.registerDefaultNetworkCallback(callback) awaitClose { connectivityManager.unregisterNetworkCallback(callback) } }.distinctUntilChanged() } } class NetworkStatusViewModel( private val connectivityObserver: ConnectivityObserver ) : ViewModel() { var connectedToInternet: Boolean by mutableStateOf(false) private set init { observeNetworkStatus() } private fun observeNetworkStatus() { viewModelScope.launch { connectivityObserver.observe().collect { status -> connectedToInternet = status == ConnectivityObserver.Status.Available } } } }
内容的提问来源于stack exchange,提问作者GVG
相关产品推荐
相关产品推荐

