Android:如何在ViewModel中创建WebView的MutableStateFlow并管理状态
实现方案
核心思路
ViewModel的职责是管理数据与业务逻辑,直接持有WebView实例会引发内存泄漏(WebView关联Context),也不符合架构设计原则。正确的做法是:ViewModel管理WebView的状态数据,Compose侧通过rememberWebViewStateWithHTMLData创建WebView状态,两者联动实现需求。
1. ViewModel实现(管理状态与业务逻辑)
ViewModel仅存储WebView的加载内容、获取到的HTML结果,不持有任何View实例:
class WebViewModel : ViewModel() { // 待加载的HTML内容 private val _webContent = MutableStateFlow("") val webContent: StateFlow<String> = _webContent // 存储获取到的页面HTML private val _pageHtml = MutableStateFlow<String?>(null) val pageHtml: StateFlow<String?> = _pageHtml // 更新要加载的HTML fun updateWebContent(html: String) { _webContent.value = html } // 处理WebView返回的HTML结果 fun onPageHtmlReceived(html: String?) { _pageHtml.value = html println("页面HTML:$html") } }
2. Compose侧实现(结合rememberWebViewStateWithHTMLData)
使用Jetpack提供的rememberWebViewStateWithHTMLData管理WebView加载状态,同时绑定ViewModel的逻辑:
@Composable fun WebViewScreen(viewModel: WebViewModel = viewModel()) { val webContent by viewModel.webContent.collectAsStateWithLifecycle() val pageHtml by viewModel.pageHtml.collectAsStateWithLifecycle() // 创建WebView状态,传入要加载的HTML数据 val webViewState = rememberWebViewStateWithHTMLData( htmlData = webContent, baseUrl = "https://your-base-url.com" // 根据实际场景配置baseUrl ) // 渲染WebView AndroidView( factory = { context -> WebView(context).apply { settings.javaScriptEnabled = true // 必须启用JS才能调用evaluateJavascript webViewClient = object : WebViewClient() { override fun onPageFinished(view: WebView?, url: String?) { super.onPageFinished(view, url) // 页面加载完成后,执行JS获取完整HTML view?.evaluateJavascript("(function() { return document.documentElement.outerHTML; })()") { html -> viewModel.onPageHtmlReceived(html) } } } } }, update = { webView -> // 当ViewModel中的HTML内容更新时,重新加载页面 val currentData = (webViewState.content as? WebContent.Data)?.data if (currentData != webContent) { webView.loadDataWithBaseURL(webViewState.baseUrl, webContent, "text/html", "UTF-8", null) } } ) // 可选:展示获取到的HTML结果 pageHtml?.let { Text( text = "获取到的页面HTML:$it", modifier = Modifier.padding(16.dp) ) } }
关键说明
- 避免ViewModel持有WebView实例:WebView依赖Android Context,ViewModel的生命周期长于UI,直接持有会导致内存泄漏。
rememberWebViewStateWithHTMLData:Jetpack官方提供的Compose WebView状态管理API,能自动绑定Compose生命周期,避免状态丢失或异常。- JS调用时机:必须在
onPageFinished回调中执行evaluateJavascript,确保页面已完全加载,能正确获取到完整HTML。
内容的提问来源于stack exchange,提问作者Slava
相关产品推荐
相关产品推荐

