【发布时间】:2022-01-07 07:03:01
【问题描述】:
我有一个通过HorizontalPager 模拟ViewPager 行为的应用程序。每个寻呼机都有一个WebView,ViewPager 会为远离当前页面的页面释放WebView。我应该在 Jetpack Compose 中做什么?看来组合组件不应该被销毁
【问题讨论】:
标签: android android-webview android-jetpack-compose
我有一个通过HorizontalPager 模拟ViewPager 行为的应用程序。每个寻呼机都有一个WebView,ViewPager 会为远离当前页面的页面释放WebView。我应该在 Jetpack Compose 中做什么?看来组合组件不应该被销毁
【问题讨论】:
标签: android android-webview android-jetpack-compose
这是预期的行为。 ViewPager 是一个惰性视图,它不会存储不可见的视图。
在明确的 Compose 中,您需要缓存的只是滚动位置和其他一些状态变量,而 Compose 会这样做。
但是当您使用AndroidView 时,您必须自己管理它。我不确定是否可以检索 WebView 滚动位置,但即使可以 - 页面仍然会重新加载。
一种可能的解决方案是将WebViews 存储为如下状态:
val webViews = remember(LocalContext.current) { mutableStateMapOf<Int, WebView>() }
val state = rememberPagerState()
LaunchedEffect(state.currentPage) {
webViews.keys.forEach { key ->
val maxCacheDistance = 3
if (abs(key - state.currentPage) >= maxCacheDistance) {
webViews.remove(key)
println("webView $key deinited")
}
}
}
HorizontalPager(
count = 10,
state = state,
) { page ->
val url = "https://duckduckgo.com/?q=$page"
AndroidView(
factory = { context ->
webViews[page] ?: run {
WebView(context).also { webView ->
webView.settings.javaScriptEnabled = true
webViews[page] = webView
}
}
},
update = { webView ->
if (webView.url != url) {
webView.loadUrl(url)
}
},
modifier = Modifier.fillMaxSize()
)
}
【讨论】:
HorizontalPager 工作很懒,它不会调用所有页面的内容。在初始加载时,它只会加载第一个和第二个项目。
您应该向实现 WebView 的类添加一个函数,该函数调用 onDestroy 并将当前页面替换为空白页面。用空白页面替换当前网页将终止任何 javascript。例如,在我的应用中,我使用 WebView 来播放 YouTube 视频:
class VideoPlayerView() : WebView(ctx) {
fun terminateWebView() {
// Reload the webview with a blank page. This is needed to kill any video playing.
loadData("<html><body></body></html>", "text/html", "base64")
this.destroy()
}
}
当您导航回上一个屏幕时,您应该调用您的终止函数。是否要在滑动标签时清除 web 视图是您必须做出的决定。在我的应用程序中,因为我在一个选项卡中播放视频,所以当用户滑动到另一个选项卡时,我需要终止视频。但是如果您的应用没有播放视频等媒体内容,那么您可能不需要终止 webview。
【讨论】: