You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 03:05:47