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

WebView所在Activity失去焦点触发onDestroy,如何让其保持存活?

解决WebView Activity切后台被销毁需重复登录的问题

问题原因

当应用退至后台时,系统会为前台运行的应用(如身份验证器)释放内存,优先级较低的后台Activity会被优先回收,你的代码没有做状态持久化,Activity重建后会重新走初始化逻辑,导致需要重复登录。

修复方案

1. 避免配置变更触发Activity销毁

在AndroidManifest.xml中为该Activity添加configChanges配置,普通配置变化(如屏幕旋转、输入法弹出、深色模式切换等)不会触发Activity销毁重建:

<activity
    android:name=".AGenericWebView"
    android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize|screenLayout|uiMode" />

2. 实现WebView状态保存与恢复

重写Activity的状态保存方法,就算Activity被系统强制销毁,重建时也可以直接恢复WebView的页面状态、登录态,不需要重新加载:

public class AGenericWebView extends AppCompatActivity {
    private WebView webView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_a_generic_web_view);
        webView = findViewById(R.id.mainWebView);
        ImageButton backButton = findViewById(R.id.backButton);

        backButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onBackPressed();
            }
        });
        webView.getSettings().setJavaScriptEnabled(true);
        TextView title = findViewById(R.id.title);
        webView.setWebViewClient(new WebViewClient());
        WebSettings settings = webView.getSettings();
        settings.setSaveFormData(true);
        settings.setDomStorageEnabled(true);
        CookieManager.getInstance().setAcceptThirdPartyCookies(webView, true);

        // 恢复状态优先于加载新页面
        if (savedInstanceState != null) {
            webView.restoreState(savedInstanceState);
            Bundle intentBundle = getIntent().getExtras();
            title.setText(intentBundle.containsKey("title")
                    ? intentBundle.getString("title")
                    : getResources().getString(R.string.navigazione));
        } else {
            // 原有加载url/html的逻辑
            Bundle intentBundle = getIntent().getExtras();
            title.setText(intentBundle.containsKey("title")
                    ? intentBundle.getString("title")
                    : getResources().getString(R.string.navigazione));
            if (intentBundle.containsKey("cookie") && intentBundle.containsKey("url")) {
                final String cookie = intentBundle.getString("cookie");
                final String url = intentBundle.getString("url");
                CookieManager.getInstance().setCookie(url, cookie);
                webView.loadUrl(url);
                webView.setWebChromeClient(new WebChromeClient() {
                    @Override
                    public void onProgressChanged(WebView view, int progress) {
                        setProgress(progress * 100);
                    }
                });
                webView.setWebViewClient(new WebViewClient());
            } else if (intentBundle.containsKey("html")) {
                String htmlData = intentBundle.getString("html");
                webView.loadData(htmlData, "text/html", "UTF-8");
            } else if (intentBundle.containsKey("url")) {
                String url = intentBundle.getString("url");
                if (intentBundle.containsKey("postdata")) {
                    String postData = intentBundle.getString("postdata");
                    byte[] postDataBytes = EncodingUtils.getBytes(postData, "BASE64");
                    webView.postUrl(url, postDataBytes);
                } else {
                    webView.loadUrl(url);
                }
            }
        }
    }

    @Override
    protected void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);
        // 保存WebView当前状态
        webView.saveState(outState);
    }

    @Override
    protected void onPause() {
        super.onPause();
        // 持久化Cookie到本地,避免进程被杀死后Cookie丢失
        CookieManager.getInstance().flush();
    }
}

3. 修复原有代码的逻辑漏洞

  • 删掉重复的webView.getSettings().setSaveFormData(false)代码,避免表单数据无法保存
  • 最后一个加载分支没有postData时,不要用webView.postUrl(url, null),改成webView.loadUrl(url),避免不必要的POST请求导致登录态失效
  • 不要依赖Intent传递的Cookie做单次设置,开启Cookie持久化后,CookieManager会自动携带对应域名的Cookie,不需要每次启动都手动设置

4. 降低进程被回收优先级

可以在AndroidManifest.xml的<application>标签中添加android:largeHeap="true"申请更大的内存空间,减少后台时被系统回收的概率,但注意不要滥用该配置,会导致应用运行时占用内存过高。

注意:不要尝试通过非法保活手段强行阻止系统销毁Activity,不符合Android系统设计规范,还会增加应用功耗,容易被应用商店、系统安全机制拦截。做好状态恢复即可让用户无感知,不需要强行保活Activity。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 18:15:03