From 6b35cbb328ee230e3af14b77c32012f003083ad1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Mlynari=C4=8D?= Date: Wed, 10 Apr 2024 11:48:08 +0200 Subject: [PATCH 1/2] Offload connectivity monitor to a background thread Change-Id: I9a2ef7766ae6abc6d8a7c86a4b49ef3c795e446c --- .../util/ConnectivityManagerNetworkMonitor.kt | 72 +++++++++++-------- 1 file changed, 43 insertions(+), 29 deletions(-) diff --git a/core/data/src/main/kotlin/com/google/samples/apps/nowinandroid/core/data/util/ConnectivityManagerNetworkMonitor.kt b/core/data/src/main/kotlin/com/google/samples/apps/nowinandroid/core/data/util/ConnectivityManagerNetworkMonitor.kt index e9599c555..a3cad57f9 100644 --- a/core/data/src/main/kotlin/com/google/samples/apps/nowinandroid/core/data/util/ConnectivityManagerNetworkMonitor.kt +++ b/core/data/src/main/kotlin/com/google/samples/apps/nowinandroid/core/data/util/ConnectivityManagerNetworkMonitor.kt @@ -26,57 +26,71 @@ import android.net.NetworkRequest.Builder import android.os.Build.VERSION import android.os.Build.VERSION_CODES import androidx.core.content.getSystemService +import androidx.tracing.Trace +import androidx.tracing.trace +import com.google.samples.apps.nowinandroid.core.network.Dispatcher +import com.google.samples.apps.nowinandroid.core.network.NiaDispatchers.IO import dagger.hilt.android.qualifiers.ApplicationContext +import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.flow.conflate +import kotlinx.coroutines.flow.flowOn import javax.inject.Inject internal class ConnectivityManagerNetworkMonitor @Inject constructor( @ApplicationContext private val context: Context, + @Dispatcher(IO) private val ioDispatcher: CoroutineDispatcher, ) : NetworkMonitor { override val isOnline: Flow = callbackFlow { - val connectivityManager = context.getSystemService() - if (connectivityManager == null) { - channel.trySend(false) - channel.close() - return@callbackFlow - } + trace("NetworkMonitor.callbackFlow") { + val connectivityManager = context.getSystemService() + if (connectivityManager == null) { + channel.trySend(false) + channel.close() + return@callbackFlow + } + + /** + * The callback's methods are invoked on changes to *any* network matching the [NetworkRequest], + * not just the active network. So we can simply track the presence (or absence) of such [Network]. + */ + val callback = object : NetworkCallback() { - /** - * The callback's methods are invoked on changes to *any* network matching the [NetworkRequest], - * not just the active network. So we can simply track the presence (or absence) of such [Network]. - */ - val callback = object : NetworkCallback() { + private val networks = mutableSetOf() - private val networks = mutableSetOf() + override fun onAvailable(network: Network) { + networks += network + channel.trySend(true) + } - override fun onAvailable(network: Network) { - networks += network - channel.trySend(true) + override fun onLost(network: Network) { + networks -= network + channel.trySend(networks.isNotEmpty()) + } } - override fun onLost(network: Network) { - networks -= network - channel.trySend(networks.isNotEmpty()) + trace("NetworkMonitor.registerNetworkCallback") { + val request = Builder() + .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) + .build() + connectivityManager.registerNetworkCallback(request, callback) } - } - val request = Builder() - .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) - .build() - connectivityManager.registerNetworkCallback(request, callback) + /** + * Sends the latest connectivity status to the underlying channel. + */ + channel.trySend(connectivityManager.isCurrentlyConnected()) - /** - * Sends the latest connectivity status to the underlying channel. - */ - channel.trySend(connectivityManager.isCurrentlyConnected()) + Trace.endSection() - awaitClose { - connectivityManager.unregisterNetworkCallback(callback) + awaitClose { + connectivityManager.unregisterNetworkCallback(callback) + } } } + .flowOn(ioDispatcher) .conflate() @Suppress("DEPRECATION") From c396352d83f9bbf1d86dae3c52c89fb66a9bcd05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Mlynari=C4=8D?= Date: Wed, 10 Apr 2024 15:23:20 +0200 Subject: [PATCH 2/2] Remove forgotten Trace.endSection() Change-Id: Ib6f7678f5f1c4b0f93f1736b6453c649d6f7dc97 --- .../core/data/util/ConnectivityManagerNetworkMonitor.kt | 3 --- 1 file changed, 3 deletions(-) diff --git a/core/data/src/main/kotlin/com/google/samples/apps/nowinandroid/core/data/util/ConnectivityManagerNetworkMonitor.kt b/core/data/src/main/kotlin/com/google/samples/apps/nowinandroid/core/data/util/ConnectivityManagerNetworkMonitor.kt index a3cad57f9..b2a642cf9 100644 --- a/core/data/src/main/kotlin/com/google/samples/apps/nowinandroid/core/data/util/ConnectivityManagerNetworkMonitor.kt +++ b/core/data/src/main/kotlin/com/google/samples/apps/nowinandroid/core/data/util/ConnectivityManagerNetworkMonitor.kt @@ -26,7 +26,6 @@ import android.net.NetworkRequest.Builder import android.os.Build.VERSION import android.os.Build.VERSION_CODES import androidx.core.content.getSystemService -import androidx.tracing.Trace import androidx.tracing.trace import com.google.samples.apps.nowinandroid.core.network.Dispatcher import com.google.samples.apps.nowinandroid.core.network.NiaDispatchers.IO @@ -83,8 +82,6 @@ internal class ConnectivityManagerNetworkMonitor @Inject constructor( */ channel.trySend(connectivityManager.isCurrentlyConnected()) - Trace.endSection() - awaitClose { connectivityManager.unregisterNetworkCallback(callback) }