I am using an Android Webview and I would like to ...
# compose-android
d
I am using an Android Webview and I would like to set a "loading" message while the url is loading. I was expecting that the "update" function would get called also after the page gets loaded, but it doesn't happen. Can anyone suggest how to update a Composable-compliant boolean when the page has loaded?
Copy code
@Composable
fun MyComposable(url: String) {

    val webClient = CustomWebViewClient()
    val showLoadingMessage by remember { mutableStateOf(true) }

    Box(modifier = Modifier.fillMaxSize()) {

	    AndroidView(
	       factory = { context -> WebView(context).apply { webViewClient = webClient } },
           update = { webView -> if (!webClient.loaded) { webView.loadUrl(url) } else { showLoadingMessage = false } }
        )

        if (showLoadingMessage) {
            Text(text = "I am loading the page...")
        }

    }

}

class CustomWebViewClient: WebViewClient(){
    var loaded = false
    override fun onPageFinished(view: WebView?, url: String?) {
        loaded = true
    }
}
s
Is the
onPageFinished
not called for you when the loading is done? If yes you can use that to know about this. With that said, you seem to be creating a new WebViewClient without remembering it so on every recomposition. Then inside there you have a
loaded
value which will just be
false
all the time more or less since on each recomposition you get the new instance, while you’ve passed only the first instance you had before to your WebView in the factory lambda which should only have run once. Consider taking a look here https://github.com/google/accompanist/tree/main/web or even copy-pasting all the code from here to get a working version of a webview first and then go from there.
d
thanks! I actually didn't realize I was creating a new instance of the web client on each recomposition. Somehow I was assuming it would be remembered. But obviously it was not the case. Yes,
onPageFinished
is called correctly. I will have a look at Accompanist, hoping it's clear to understand.
@Stylianos Gakis I am now trying to remember the class and apply the @Stable annotation to the loaded property, but the composable always reads loaded = false. I guess @Stable doesn't work on remembered classes. Any suggestion?
Copy code
@Composable
fun MyComposable(url: String) {

    val webClient : CustomWebViewClient = remember { CustomWebViewClient() }

    Box(modifier = Modifier.fillMaxSize()) {

        AndroidView(
	       factory = { context -> WebView(context).apply { webViewClient = webClient } },
           update = { webView -> webView.loadUrl(url) }
        )

        if (!webClient.loaded) {
            Text(text = "I am loading the page...")
        }

    }

}

class CustomWebViewClient: WebViewClient() {
    @Stable var loaded = false
    override fun onPageFinished(view: WebView?, url: String?) {
        loaded = true
    }
}
s
Where are you reading the
loaded
from? Right now it’s just a var, there’s no way for compose to be able to observe it if it changes so that it gets the latest value out of it. If it were a
var loaded by mutableStateOf(false)
then you would probably be able to actually oberve its state. But with that said, I’d need to look at more of your code to understand what you want to happen here
d
Oh, you are right! it works if I use
var loaded by mutableStateOf(false)
on the CustomWebViewClient class
thanks!
411 Views