如何解决Android Jetpack Compose返回时的SIGSEGV崩溃问题
在Android Jetpack Compose开发场景下,从MailRoomScreen页面执行返回导航时,触发以下原生崩溃:
Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x20 in tid 19443 (RenderThread)
测试验证:将Tab页面替换为简单Text组件后,崩溃问题消失,确认问题与WebView在Compose中的生命周期管理相关。
从提供的代码来看,核心问题集中在WebView的实例管理与销毁时机上:
WebView实例重复创建与冲突销毁:
MailRoomScreen中通过remember创建WebView实例并传递给MailRoomInScreen- 但
MailRoomInScreen内部又重新通过remember创建了全新的WebView实例,同时在DisposableEffect中执行销毁逻辑 - 返回时,
MailRoomScreen的返回按钮再次调用外部WebView的destroy(),导致同一生命周期内多次销毁或销毁已释放的WebView资源,触发RenderThread内存访问错误
销毁时机不当:
- 在返回按钮点击时直接调用
webView.destroy(),此时Composable尚未完成生命周期清理,WebView可能仍处于RenderThread的渲染队列中,强制销毁导致原生层访问已释放的内存
- 在返回按钮点击时直接调用
1. 统一WebView实例管理,避免跨Composable传递
移除MailRoomScreen中创建的WebView实例,将WebView的创建与生命周期完全交给MailRoomInScreen管理:
- 修改
MailRoomScreen中调用MailRoomInScreen的代码:
// MailRoomScreen内HorizontalPager的Tab 0逻辑 0 -> { MailRoomInScreen( mailRoomViewModel = mailroomViewModel, navController = navController ) }
- 修改
MailRoomInScreen的参数定义,移除多余的WebView参数:
@Composable fun MailRoomInScreen( mailRoomViewModel: MailroomViewModel, navController: NavHostController ) { // 内部保持原有的WebView remember与DisposableEffect逻辑 }
2. 移除返回按钮中的主动销毁调用
删除MailRoomScreen返回按钮内的webView.destroy(),完全依赖MailRoomInScreen的DisposableEffect处理销毁——该Effect会在Composable从Composition中移除时自动执行,符合WebView的生命周期规律:
IconButton( onClick = { navController.popBackStack() // 仅保留导航逻辑 } ) { Icon( Icons.Filled.ArrowBack, contentDescription = "Back" ) }
3. 优化WebView销毁的安全流程
在MailRoomInScreen的DisposableEffect中,增加更安全的销毁步骤,确保WebView完全停止渲染后再释放资源:
DisposableEffect(Unit) { onDispose { webView.stopLoading() webView.loadUrl("about:blank") // 清空页面内容 webView.removeJavascriptInterface("Android") // 移除JS接口避免内存泄漏 webView.destroy() } }
4. 调整HorizontalPager的页面缓存策略
HorizontalPager默认保留相邻页面实例(offscreenLimit=1),切换到Tab 1时,Tab 0的MailRoomInScreen仍处于Composition中,不会触发销毁。若需要切换Tab时立即销毁WebView,可设置offscreenLimit=0:
HorizontalPager( state = pagerState, modifier = Modifier.fillMaxSize(), offscreenLimit = 0 ) { // 页面内容逻辑 }
内容的提问来源于stack exchange,提问作者M B

