I have the following code:
@Composable
fun WebTest(modifier: Modifier) {
val url = "https://www.google.com"
val ctx = LocalContext.current
Column(modifier = modifier) {
Text("title", fontSize = 22.sp, modifier = Modifier.fillMaxWidth().height(44.dp))
AndroidView(
modifier = Modifier.fillMaxWidth().fillMaxHeight(),
factory = { WebView(ctx) },
update = {
it.loadUrl(url)
}
)
}
}
In this case, the "title" Text
always show after the WebView was loaded into the AndroidView
, but it is supposed to be shown immediately.
If I comment out the code it.loadUrl(url)
, the "title" Text
will never show.
If I change WebView to FrameLayout, it work fine.
Why the "title" Text
cannot be show immediately?
The AndroidView
invocation is the bottleneck here. Even if you construct the View
outside of the composition, there is a significant lag when the View
is applied to the AndroidView
. This results in a very slow recomposition, where the whole Composable will go blank until all nested Composables were laid out.
However, the LazyColumn
is an exception here - as it lazily loads and lays out its children without affecting the recomposition of the parent Composable. This allows the following workaround:
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun WebTest(modifier: Modifier = Modifier) {
val url = "https://www.google.com"
val ctx = LocalContext.current
Column(modifier = modifier) {
TopAppBar(
title = { Text(text = "WebView Demonstration") },
)
LazyColumn(
modifier = Modifier.weight(1f).fillMaxHeight(),
userScrollEnabled = false // to let the AndroidView consume scrolling
) {
item {
AndroidView(
modifier = Modifier.fillParentMaxSize(),
factory = { WebView(ctx) },
update = {
it.webViewClient = WebViewClient();
it.loadUrl(url)
}
)
}
}
}
}
Comparison without / with LazyColumn
: