You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Navigation Component下Fragment中WebView状态保存失效求助

问题

使用Navigation Component从Home Fragment跳转到Web Fragment(代码中为TestFragment)加载指定URL,需求是离开Web Fragment时保存WebView状态,返回时恢复已保存状态而非重新加载页面,但当前实现无效。

当前代码:

public class TestFragment extends Fragment {

    private WebView webView;
    private Bundle webViewBundle;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.test_layout, container, false);
        webView = v.findViewById(R.id.webView);

        webView.getSettings().setJavaScriptEnabled(true);
        webView.setWebViewClient(new MyWebViewClient());
        if(webViewBundle != null){
            webView.restoreState(webViewBundle);
        } else {
            assert getArguments() != null;
            String url = getArguments().getString("url");
            webView.loadUrl(url);
        }
        return v;
    }

    @Override
    public void onViewStateRestored(@Nullable Bundle savedInstanceState) {
        super.onViewStateRestored(savedInstanceState);
        webView.restoreState(savedInstanceState);
    }

    @Override
    public void onPause() {
        super.onPause();
        webViewBundle = new Bundle();
        webView.saveState(webViewBundle);
    }

    class MyWebViewClient extends WebViewClient {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            webView.loadUrl(url);
            webView.saveState(webViewBundle);
            return true;
        }
    }
}
问题分析
  1. 状态存储位置错误:webViewBundle是Fragment的成员变量,当Fragment被Navigation Component弹出栈销毁后,该变量会被回收,重建时无法获取之前保存的状态。
  2. 保存时机与方式错误:在onPause中保存状态到成员变量,没有将状态存入Fragment的savedInstanceState,导致Fragment重建时状态丢失。
  3. 恢复逻辑混乱:onCreateView中判断成员变量webViewBundle,但该变量在重建时为空;onViewStateRestored中直接用savedInstanceState恢复,但savedInstanceState中并未保存WebView状态。
  4. 不必要的手动保存:shouldOverrideUrlLoading中调用saveState时,webViewBundle可能未初始化,会引发空指针异常,且页面加载过程中无需手动保存状态。
解决方案

将WebView状态存入Fragment的savedInstanceState,利用Fragment的生命周期方法正确保存和恢复状态:

  1. 移除自定义的webViewBundle成员变量,改用系统提供的savedInstanceState存储状态。
  2. 在onSaveInstanceState中保存WebView状态,这是Fragment销毁前系统会调用的方法,确保状态被持久化。
  3. 在onCreateView中优先从savedInstanceState恢复状态,无状态时再加载初始URL。
  4. 修正WebViewClient的逻辑,移除不必要的手动保存操作。

修改后的完整代码:

public class TestFragment extends Fragment {

    private WebView webView;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.test_layout, container, false);
        webView = v.findViewById(R.id.webView);

        // 初始化WebView基础设置
        webView.getSettings().setJavaScriptEnabled(true);
        webView.setWebViewClient(new MyWebViewClient());

        // 优先恢复保存的状态,无状态则加载初始URL
        if (savedInstanceState != null) {
            webView.restoreState(savedInstanceState);
        } else {
            assert getArguments() != null;
            String url = getArguments().getString("url");
            webView.loadUrl(url);
        }
        return v;
    }

    @Override
    public void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);
        // 将WebView状态存入系统的savedInstanceState
        webView.saveState(outState);
    }

    class MyWebViewClient extends WebViewClient {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            // 让WebView内部处理跳转,无需手动保存状态
            view.loadUrl(url);
            return true;
        }
    }
}
额外说明
  • Navigation Component中,当从Web Fragment返回Home Fragment时,Web Fragment会被销毁,再次跳转时会重建,此时savedInstanceState会携带之前保存的状态,webView.restoreState会恢复到之前的页面位置、表单内容等状态。
  • 确保WebView所在的布局中,WebView的id保持固定,避免状态恢复失败。

内容的提问来源于stack exchange,提问作者Taki

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 10:05:32