diff --git a/apollo-coroutines-support/src/main/kotlin/com/apollographql/apollo/coroutines/CoroutinesExtensions.kt b/apollo-coroutines-support/src/main/kotlin/com/apollographql/apollo/coroutines/CoroutinesExtensions.kt index f62b5b183b6..33cb269b5f8 100644 --- a/apollo-coroutines-support/src/main/kotlin/com/apollographql/apollo/coroutines/CoroutinesExtensions.kt +++ b/apollo-coroutines-support/src/main/kotlin/com/apollographql/apollo/coroutines/CoroutinesExtensions.kt @@ -23,7 +23,8 @@ import kotlinx.coroutines.flow.callbackFlow */ @ExperimentalCoroutinesApi fun ApolloCall.toFlow(): Flow> = callbackFlow { - clone().enqueue( + val clone = clone() + clone.enqueue( object : ApolloCall.Callback() { override fun onResponse(response: Response) { runCatching { @@ -42,7 +43,7 @@ fun ApolloCall.toFlow(): Flow> = callbackFlow { } } ) - awaitClose { this@toFlow.cancel() } + awaitClose { clone.cancel() } } /** @@ -53,7 +54,8 @@ fun ApolloCall.toFlow(): Flow> = callbackFlow { */ @ExperimentalCoroutinesApi fun ApolloQueryWatcher.toFlow(): Flow> = callbackFlow { - clone().enqueueAndWatch( + val clone = clone() + clone.enqueueAndWatch( object : ApolloCall.Callback() { override fun onResponse(response: Response) { runCatching { @@ -72,7 +74,7 @@ fun ApolloQueryWatcher.toFlow(): Flow> = callbackFlow { } } ) - awaitClose { this@toFlow.cancel() } + awaitClose { clone.cancel() } } @@ -116,7 +118,8 @@ fun ApolloCall.toDeferred(): Deferred> { */ @ExperimentalCoroutinesApi fun ApolloSubscriptionCall.toFlow(): Flow> = callbackFlow { - clone().execute( + val clone = clone() + clone.execute( object : ApolloSubscriptionCall.Callback { override fun onConnected() { } @@ -140,7 +143,7 @@ fun ApolloSubscriptionCall.toFlow(): Flow> = callbackFlow { } } ) - awaitClose { this@toFlow.cancel() } + awaitClose { clone.cancel() } } /** diff --git a/apollo-integration/src/test/java/com/apollographql/apollo/CoroutinesApolloTest.kt b/apollo-integration/src/test/java/com/apollographql/apollo/CoroutinesApolloTest.kt index ba698c8a8de..7d7a3daed7c 100644 --- a/apollo-integration/src/test/java/com/apollographql/apollo/CoroutinesApolloTest.kt +++ b/apollo-integration/src/test/java/com/apollographql/apollo/CoroutinesApolloTest.kt @@ -12,6 +12,8 @@ import com.apollographql.apollo.coroutines.toFlow import com.apollographql.apollo.coroutines.toJob import com.apollographql.apollo.exception.ApolloException import com.apollographql.apollo.integration.normalizer.EpisodeHeroNameQuery +import com.apollographql.apollo.integration.normalizer.HeroNameQuery +import com.apollographql.apollo.integration.normalizer.HeroNameWithIdQuery import com.apollographql.apollo.integration.normalizer.type.Episode import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -149,6 +151,29 @@ class CoroutinesApolloTest { assertThat(response.data!!.hero()!!.name()).isEqualTo("R2-D2") } + @Test + @ExperimentalCoroutinesApi + fun watcherFlowCancellationCancelsWatcher(): Unit = runBlocking { + server.enqueue(mockResponse("HeroNameWithIdResponse.json")) + apolloClient + .query(HeroNameWithIdQuery()) + .watcher() + .toFlow() + .first() // Cancels the flow after first response + + apolloClient.clearNormalizedCache() + apolloClient.clearHttpCache() + + server.enqueue(mockResponse("HeroNameResponse.json")) + apolloClient + .query(HeroNameQuery()) + .watcher() + .toFlow() + .first() + + assertThat(server.requestCount).isEqualTo(2) + }.let { } + companion object { private const val FILE_EPISODE_HERO_NAME_WITH_ID = "EpisodeHeroNameResponseWithId.json"