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

Android WebView应用被系统杀死后,如何维护/重建数据库连接?

问题描述

我开发了一个内嵌HTML、CSS、JS的WebView Android应用,配备多个本地数据库存储数据,该应用每次需连续使用10-11小时。
目前发现一个严重问题:应用进入后台一段时间后会被Android系统杀死,导致所有任务需重新执行。我需要维护或重建Android与数据库的连接,以确保应用稳定运行。

我想咨询两个问题:

  1. 是否有办法维护Android与数据库的连接(例如使用前台服务),使应用被杀死后不影响连接?
  2. 应用被系统杀死后,能否让Android与JS重建连接(例如进行数据库同步)?

相关代码

MainActivity代码

public class MainActivity extends AppCompatActivity
{
    HTMLDataBase myDB1;
    ContentTableDataBase myDB2;
    CloudTableDataBase myDB3;
    InterviewDataBase myDB4;
    Context context;
    boolean check;
    private WebView view;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        myDB1 = new HTMLDataBase(this);
        myDB2 = new ContentTableDataBase(this);
        myDB3 = new CloudTableDataBase(this); 
        myDB4 = new InterviewDataBase(this); 

        display_html();
        Javascript_Android_Communication();
    }

    @Override
    protected void onResume()
    {
        super.onResume();

        myDB1 = new HTMLDataBase(this); 
        myDB2 = new ContentTableDataBase(this); 
        myDB3 = new CloudTableDataBase(this);
        myDB4 = new InterviewDataBase(this);

        display_html();
        Javascript_Android_Communication();
    }

    @Override
    protected void onStop()
    {
        super.onStop();

        this.finish();
    }

    public void display_html()
    {
        WebView view = (WebView) findViewById(R.id.WebView);
        view.getSettings().setJavaScriptEnabled(true);
        view.getSettings().setDomStorageEnabled(true);
        view.loadUrl("file:///android_asset/index.html");
    }

    public void Javascript_Android_Communication()
    {
        WebView view = (WebView) findViewById(R.id.WebView);
        view.setWebChromeClient(new WebChromeClient() {});
        WebSettings settings = view.getSettings();
        settings.setJavaScriptEnabled(true);
        settings.setDomStorageEnabled(true);

        view.addJavascriptInterface(new JavaScriptInterface(this), "Android");
        view.addJavascriptInterface(new WebViewJavaScriptInterface(this), "app");
    }
}

WebViewJavaScriptInterface代码

public class WebViewJavaScriptInterface
{
    HTMLDataBase myDB1;
    ContentTableDataBase myDB2;
    CloudTableDataBase myDB3;
    InterviewDataBase myDB4;
    Context mContext;

    WebViewJavaScriptInterface (Context c)
    {
        mContext = c;
    }
    @JavascriptInterface
    public void Javascript_to_Android(String data_id, String html_element, String state)
    {
        myDB1 = new HTMLDataBase((MainActivity) mContext);
        myDB1.updateData(data_id, html_element, state);
    }

    @JavascriptInterface
    public void Javascript_to_Content_Table_DataBase(String data_id, String duty_time, String my_duty, String checkbox)
    {
        myDB2 = new ContentTableDataBase((MainActivity) mContext);
        myDB2.insertData(data_id, duty_time, my_duty, checkbox);
    }


    @JavascriptInterface
    public void add_cloud_data(String data_id, String Time, String Total_Cloud, String Low_Medium_Cloud, String FirstCloud,
                           String SecondCloud, String ThirdCloud, String ForthCloud, String FifthCloud, String SixthCloud,
                           String SeventhCloud, String EighthCloud, String Visibility)
    {
        myDB3 = new CloudTableDataBase((MainActivity) mContext);
        boolean response = myDB3.insertData(data_id, Time, Total_Cloud, Low_Medium_Cloud, FirstCloud, SecondCloud, ThirdCloud, ForthCloud, FifthCloud, SixthCloud, SeventhCloud, EighthCloud, Visibility);
        if (response == true)
        {
            Toast.makeText(mContext, "Data inserted", Toast.LENGTH_SHORT).show();
        }

        if (response == false)
        {
            Toast.makeText(mContext, "Data not inserted", Toast.LENGTH_SHORT).show();
        }
    }

    @JavascriptInterface
    public void update_cloud_data(String data_id, String Time, String Total_Cloud, String Low_Medium_Cloud, String FirstCloud,
                           String SecondCloud, String ThirdCloud, String ForthCloud, String FifthCloud, String SixthCloud,
                           String SeventhCloud, String EighthCloud, String Visibility)
    {
        myDB3 = new CloudTableDataBase((MainActivity) mContext);
        boolean response = myDB3.updateData(data_id, Time, Total_Cloud, Low_Medium_Cloud, FirstCloud, SecondCloud, ThirdCloud, ForthCloud, FifthCloud, SixthCloud, SeventhCloud, EighthCloud, Visibility);
        if (response == true)
        {
            Toast.makeText(mContext, "Data updated", Toast.LENGTH_SHORT).show();
        }

        if (response == false)
        {
            Toast.makeText(mContext, "Data not updated", Toast.LENGTH_SHORT).show();
        }
    }

    @JavascriptInterface
    public void delete_duty(String id)
    {
        myDB2.deleteData(id);
    }

    @JavascriptInterface
    public void delete_cloud(String id)
    {
        myDB3.deleteData(id);
    }
}

解决方案

针对问题1:维护数据库连接&降低应用被杀死概率

首先明确:应用进程被系统完全杀死后,所有进程内资源(包括数据库连接)都会被释放,无法维持连接。但可以通过以下方式优化,降低被杀死的概率,并在重启后快速恢复数据库操作:

  1. 使用前台服务
    前台服务会在状态栏显示通知,系统优先级更高,不容易被回收。可以将核心数据操作(如定时同步、批量持久化)放在前台服务中,但注意不要长期持有数据库连接——SQLite自带连接池管理,每次操作后关闭连接反而更稳定,避免内存泄漏。
    实现要点:创建继承Service的类,在onStartCommand中调用startForeground传入通知ID和通知实例,将服务置于前台状态。

  2. 优化数据库连接管理
    你的代码中每次JS调用都新建数据库实例,会频繁打开/关闭连接,建议用单例模式复用数据库实例:

    // 示例:HTMLDataBase单例实现
    public class HTMLDataBase extends SQLiteOpenHelper {
        private static HTMLDataBase instance;
        
        public static synchronized HTMLDataBase getInstance(Context context) {
            if (instance == null) {
                instance = new HTMLDataBase(context.getApplicationContext());
            }
            return instance;
        }
        
        private HTMLDataBase(Context context) {
            super(context, "html_db", null, 1);
        }
    }
    

    后续所有数据库操作都通过getInstance获取实例,减少连接开销。

  3. 移除不必要的Activity销毁逻辑
    你在onStop中调用this.finish(),会导致应用进入后台时直接销毁Activity,大幅提升被系统回收的概率。建议移除该行代码,让Activity正常进入后台栈:

    @Override
    protected void onStop() {
        super.onStop();
        // 移除 this.finish();
    }
    

针对问题2:应用被杀死后重建Android与JS的连接

应用被完全杀死后,WebView和JS环境都会被销毁,无法直接重建之前的连接,但可以通过以下方式实现数据同步和状态恢复:

  1. 启动时主动同步数据
    在MainActivity中,监听WebView页面加载完成事件,主动调用JS方法同步本地数据库数据:

    view.setWebViewClient(new WebViewClient() {
        @Override
        public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
            // 将本地数据库数据转为JSON,调用JS方法同步
            view.evaluateJavascript("syncAndroidData(" + getDatabaseDataAsJson() + ")", null);
        }
    });
    

    需实现getDatabaseDataAsJson()方法,把数据库数据转换成JSON格式传递给JS,让JS恢复之前的操作状态。

  2. 用WorkManager实现后台同步
    如果需要在应用被杀死后仍能进行数据库同步(如与云端同步),可以使用WorkManager创建周期性任务。WorkManager的任务会持久化,即使设备重启也能继续执行,适合长时间后台同步需求。

  3. 保存关键状态到本地
    在Activity的onSaveInstanceState中保存关键状态(如当前操作的任务ID、未完成的数据),重启时从Bundle中恢复并传递给JS:

    private String currentTaskId;
    
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putString("currentTaskId", currentTaskId);
    }
    
    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        currentTaskId = savedInstanceState.getString("currentTaskId");
        // 恢复后传递给JS
        view.evaluateJavascript("restoreTaskState('" + currentTaskId + "')", null);
    }
    

代码优化建议
  1. 复用WebView实例
    你的display_html和Javascript_Android_Communication方法每次都重新获取WebView实例,建议在onCreate中初始化一次并保存为成员变量,避免重复查找和配置:

    private WebView view;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        view = findViewById(R.id.WebView);
        setupWebViewSettings();
        
        myDB1 = HTMLDataBase.getInstance(this);
        myDB2 = ContentTableDataBase.getInstance(this);
        myDB3 = CloudTableDataBase.getInstance(this);
        myDB4 = InterviewDataBase.getInstance(this);
        
        view.loadUrl("file:///android_asset/index.html");
        setupJavascriptInterfaces();
    }
    
    private void setupWebViewSettings() {
        WebSettings settings = view.getSettings();
        settings.setJavaScriptEnabled(true);
        settings.setDomStorageEnabled(true);
        view.setWebChromeClient(new WebChromeClient() {});
    }
    
    private void setupJavascriptInterfaces() {
        view.addJavascriptInterface(new JavaScriptInterface(this), "Android");
        view.addJavascriptInterface(new WebViewJavaScriptInterface(this), "app");
    }
    
  2. 优化数据库操作
    在WebViewJavaScriptInterface中,将新建数据库实例改为使用单例:

    @JavascriptInterface
    public void Javascript_to_Android(String data_id, String html_element, String state) {
        HTMLDataBase myDB1 = HTMLDataBase.getInstance(mContext);
        myDB1.updateData(data_id, html_element, state);
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 11:44:54