如何在Fragment中保存WebView的完整状态?
解决WebView完整状态保存问题
1. 核心问题分析
当前实现的问题在于:
- 每次进入
HomeFragment都会重新创建WebView实例,旧实例被销毁后,仅靠Bundle无法完整恢复滚动位置、视频进度这类运行时状态 saveState的时机和WebView的生命周期绑定逻辑有误,导致状态保存不完整restoreState本身依赖WebView配置一致性,且仅靠Bundle无法替代WebView实例的持续存在
2. 具体解决方案
修改ViewModel:复用WebView实例
将WebView实例保存在ViewModel中,避免Fragment视图销毁时WebView被回收:
class WebViewModel : ViewModel() { var webView: CustomWebView? = null private val webViewState = Bundle() // 确保WebView仅初始化一次 fun initWebView(context: Context): CustomWebView { return webView ?: run { CustomWebView(context).apply { // 配置WebView核心参数,必须和后续恢复时一致 settings.javaScriptEnabled = true settings.domStorageEnabled = true settings.cacheMode = WebSettings.LOAD_DEFAULT settings.mediaPlaybackRequiresUserGesture = false webView = this } } } fun saveWebViewState() { webView?.saveState(webViewState) } fun restoreWebViewState() { webView?.restoreState(webViewState) } }
修改HomeFragment:优化生命周期逻辑
在Fragment视图销毁时仅移除WebView而非销毁,返回时直接复用实例:
class HomeFragment : Fragment() { private lateinit var binding: FragmentHomeBinding private val viewModel: WebViewModel by viewModels() override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { binding = FragmentHomeBinding.inflate(inflater, container, false) return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) initWebView() setupBottomBarListeners() } private fun initWebView() { val webView = viewModel.initWebView(requireContext()) // 避免重复添加WebView到布局 if (webView.parent != null) { (webView.parent as ViewGroup).removeView(webView) } binding.frameLayout.addView(webView) // 首次加载默认页面 if (webView.url == null) { webView.loadUrl("https://google.com") } else { viewModel.restoreWebViewState() } } private fun setupBottomBarListeners() { binding.apply { layoutBottomBar.rLTextBarContainer.setOnClickListener { showSearchFragment() } layoutBottomBar.ivBottomMenu.setOnClickListener { showBottomMenu() } layoutBottomBar.ivRefreshOrCancel.setOnClickListener { refreshOrCancelClicked() } } } override fun onPause() { super.onPause() viewModel.webView?.onPause() viewModel.saveWebViewState() } override fun onResume() { super.onResume() viewModel.webView?.onResume() } override fun onDestroyView() { // 仅移除WebView,不销毁实例 binding.frameLayout.removeView(viewModel.webView) super.onDestroyView() } }
3. 关键注意事项
- 必须保证WebView的初始化配置(如JS启用、DOM存储、缓存模式)全程一致,否则
restoreState会失效 - 调用
webView.onPause()/webView.onResume()可同步页面媒体播放状态,确保视频进度保留 - 若自定义
CustomWebView,不要重写saveState/restoreState方法,避免破坏原生逻辑
内容的提问来源于stack exchange,提问作者Waqas Younis
相关产品推荐
相关产品推荐

