diff --git a/web/api/current.api b/web/api/current.api index cd49cf2a1..d90966187 100644 --- a/web/api/current.api +++ b/web/api/current.api @@ -75,7 +75,7 @@ package com.google.accompanist.web { } public final class WebViewKt { - method @androidx.compose.runtime.Composable public static void WebView(com.google.accompanist.web.WebViewState state, optional androidx.compose.ui.Modifier modifier, optional boolean captureBackPresses, optional com.google.accompanist.web.WebViewNavigator navigator, optional kotlin.jvm.functions.Function1 onCreated, optional com.google.accompanist.web.AccompanistWebViewClient client, optional com.google.accompanist.web.AccompanistWebChromeClient chromeClient); + method @androidx.compose.runtime.Composable public static void WebView(com.google.accompanist.web.WebViewState state, optional androidx.compose.ui.Modifier modifier, optional boolean captureBackPresses, optional com.google.accompanist.web.WebViewNavigator navigator, optional kotlin.jvm.functions.Function1 onCreated, optional kotlin.jvm.functions.Function1 onDispose, optional com.google.accompanist.web.AccompanistWebViewClient client, optional com.google.accompanist.web.AccompanistWebChromeClient chromeClient); method @androidx.compose.runtime.Composable public static com.google.accompanist.web.WebViewNavigator rememberWebViewNavigator(optional kotlinx.coroutines.CoroutineScope coroutineScope); method @androidx.compose.runtime.Composable public static com.google.accompanist.web.WebViewState rememberWebViewState(String url, optional java.util.Map additionalHttpHeaders); method @androidx.compose.runtime.Composable public static com.google.accompanist.web.WebViewState rememberWebViewStateWithHTMLData(String data, optional String? baseUrl); diff --git a/web/src/androidTest/kotlin/com/google/accompanist/web/WebTest.kt b/web/src/androidTest/kotlin/com/google/accompanist/web/WebTest.kt index 6fb3670d2..747744473 100644 --- a/web/src/androidTest/kotlin/com/google/accompanist/web/WebTest.kt +++ b/web/src/androidTest/kotlin/com/google/accompanist/web/WebTest.kt @@ -21,6 +21,7 @@ import android.webkit.WebView import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.MutableState import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.snapshotFlow @@ -593,6 +594,29 @@ class WebTest { mockServer.shutdown() } + @Test + fun testOnDisposeCalled() { + lateinit var state: WebViewState + lateinit var toggle: MutableState + var isOnDisposeCalled = false + + rule.setContent { + toggle = remember { mutableStateOf(true) } + if (toggle.value) { + state = rememberWebViewStateWithHTMLData(data = TEST_DATA) + WebTestContent( + state, + idleResource, + onDispose = { isOnDisposeCalled = true }, + ) + } + } + + toggle.value = false + webNode.assertDoesNotExist() + assertThat(isOnDisposeCalled).isTrue() + } + private val webNode: SemanticsNodeInteraction get() = rule.onNodeWithTag(WebViewTag) } @@ -614,6 +638,7 @@ private fun WebTestContent( webViewState: WebViewState, idlingResource: WebViewIdlingResource, navigator: WebViewNavigator = rememberWebViewNavigator(), + onDispose: (WebView) -> Unit = {}, client: AccompanistWebViewClient = remember { AccompanistWebViewClient() }, chromeClient: AccompanistWebChromeClient = remember { AccompanistWebChromeClient() } ) { @@ -625,6 +650,7 @@ private fun WebTestContent( modifier = Modifier.testTag(WebViewTag), navigator = navigator, onCreated = { it.settings.javaScriptEnabled = true }, + onDispose = onDispose, client = client, chromeClient = chromeClient ) diff --git a/web/src/main/java/com/google/accompanist/web/WebView.kt b/web/src/main/java/com/google/accompanist/web/WebView.kt index dcc66972a..e89ff1252 100644 --- a/web/src/main/java/com/google/accompanist/web/WebView.kt +++ b/web/src/main/java/com/google/accompanist/web/WebView.kt @@ -25,6 +25,7 @@ import android.webkit.WebView import android.webkit.WebViewClient import androidx.activity.compose.BackHandler import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.Immutable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.Stable @@ -33,6 +34,7 @@ import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.rememberUpdatedState import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalInspectionMode @@ -68,6 +70,7 @@ fun WebView( captureBackPresses: Boolean = true, navigator: WebViewNavigator = rememberWebViewNavigator(), onCreated: (WebView) -> Unit = {}, + onDispose: (WebView) -> Unit = {}, client: AccompanistWebViewClient = remember { AccompanistWebViewClient() }, chromeClient: AccompanistWebChromeClient = remember { AccompanistWebChromeClient() } ) { @@ -81,6 +84,14 @@ fun WebView( with(navigator) { webView?.handleNavigationEvents() } } + val currentOnDispose by rememberUpdatedState(onDispose) + + webView?.let { it -> + DisposableEffect(it) { + onDispose { currentOnDispose(it) } + } + } + // Set the state of the client and chrome client // This is done internally to ensure they always are the same instance as the // parent Web composable