Jetpack Compose - store internet connection state in view model

762 views Asked by At

I have the below code to check the live network connection state.

How can I call the function to start checking for this network connection state from the view model init function?

How can I also make it so if there is a change in internet connection state, it updates this in the view model?

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)
                    launch { send(ConnectivityObserver.Status.Available) }
                }

                override fun onLosing(network: Network, maxMsToLive: Int) {
                    super.onLosing(network, maxMsToLive)
                    launch { send(ConnectivityObserver.Status.Losing) }
                }

                override fun onLost(network: Network) {
                    super.onLost(network)
                    launch { send(ConnectivityObserver.Status.Lost) }
                }

                override fun onUnavailable() {
                    super.onUnavailable()
                    launch { send(ConnectivityObserver.Status.Unavailable) }
                }
            }

            connectivityManager.registerDefaultNetworkCallback(callback)

            awaitClose {
                connectivityManager.unregisterNetworkCallback(callback)
            }
        }.distinctUntilChanged()
    }


}


class NetworkStatusViewModel : ViewModel() {

    var connectedToInternet: Boolean by mutableStateOf(false)

    init {
        connectedToInternet = checkNetworkConnection()

    }
}


fun checkNetworkConnection(): Boolean {
    //Make call here to start checking on network connection and return a boolean
    //return true if connected to the internet
    //return false if not connected to the internet
}
1

There are 1 answers

5
Subfly On

just create a state variable in your viewmodel such as:

private val _connectivityState = mutableStateOf(Status. Unavailable)
val connectivityState: State<Status> = _connectivityState // this is for exposing UI if you need

then there are two possible scenarios:

1- if you want to do some work in case of connectivity changes, directly use a combine flow and connect your different flows such as:

fun someWork() {
    viewModelScope.launch(Dispatchers.IO) {
        combine(
             ConnectivityObserver.observe(),
             YourAnotherWorkStuffReturnsAFlow()
        ).collect { status, payloadOfWork ->
              _connectivityState = status
              when(status) {
                   // check payload and do work
              }
        }
    }
}

2- directly call your observer as above in a separate vievmodelScope and update value on collect changes. the code will be same except the combine part and other workload such as :

init{
   getConnectivity()
}
fun getConnectivity() {
    viewModelScope.launch(Dispatchers.IO) {
        ConnectivityObserver.observe().collect { status ->
              _connectivityState = status
        }
    }
}

Finally, by using two variables, which are given in the beginning, you will ensure that UI cannot make any changes on _connectivityState as only the connectivityState is exposed to the UI and it only observes through _connectivityState.