如何在 Jetpack Compose 上回收 WebView?
How to recycle a webview on jetpack compose?
我有一个通过 HorizontalPager
模拟 ViewPager
行为的应用程序。每个Pager都有一个WebView
,ViewPager
会为远离当前页面的页面释放WebView
。我应该在 Jetpack Compose 中做什么?似乎不应该销毁可组合项
您应该向 class 添加一个函数来实现调用 onDestroy 的 WebView 并将当前页面替换为空白页面。用空白页面替换当前网页将终止任何 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()
}
}
当您导航回到上一屏幕时,您应该调用终止函数。滑动标签时是否要清除 webview 是您必须做出的决定。在我的应用程序中,因为我在一个选项卡中播放视频,所以我需要在用户滑动到另一个选项卡时终止视频。但是,如果您的应用不播放视频等媒体内容,那么您可能不需要终止 webview。
这是预期的行为。 ViewPager
是惰性视图,不会存储不可见视图。
在 Clear 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
模拟 ViewPager
行为的应用程序。每个Pager都有一个WebView
,ViewPager
会为远离当前页面的页面释放WebView
。我应该在 Jetpack Compose 中做什么?似乎不应该销毁可组合项
您应该向 class 添加一个函数来实现调用 onDestroy 的 WebView 并将当前页面替换为空白页面。用空白页面替换当前网页将终止任何 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()
}
}
当您导航回到上一屏幕时,您应该调用终止函数。滑动标签时是否要清除 webview 是您必须做出的决定。在我的应用程序中,因为我在一个选项卡中播放视频,所以我需要在用户滑动到另一个选项卡时终止视频。但是,如果您的应用不播放视频等媒体内容,那么您可能不需要终止 webview。
这是预期的行为。 ViewPager
是惰性视图,不会存储不可见视图。
在 Clear 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()
)
}