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

应用启动或重建时,如何正确执行数据库数据转换长任务?

解决方案

核心思路是不要阻塞主线程(否则会触发ANR应用无响应),而是把所有依赖转换后数据的初始化逻辑,放到数据转换完成后的回调中执行,同时在后台线程完成转换,UI线程只负责显示/关闭加载对话框。

方法一:使用Handler切换线程

  1. 定义Handler用于后台线程完成后通知UI线程:
private Handler mMainHandler = new Handler(Looper.getMainLooper());
  1. 修改convertDataInDB方法,在转换完成后关闭对话框并执行后续逻辑:
public void convertDataInDB() {
    // 创建并显示不可取消的加载对话框
    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setCancelable(false); 
    builder.setView(R.layout.progress_dialog);
    final AlertDialog dialog = builder.create();
    dialog.show();

    // 后台线程执行数据转换
    new Thread(() -> {
        db.convertData();
        
        // 转换完成后切换回UI线程
        mMainHandler.post(() -> {
            dialog.dismiss();
            // 执行所有依赖新数据的初始化操作
            initAfterConversion();
        });
    }).start();  
}
  1. 重构onCreate,将原有的后续逻辑移到initAfterConversion方法:
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    
    // 初始化数据库等基础组件
    initDB();
    
    // 启动数据转换
    convertDataInDB();
    
    // 不要在这里写需要操作新数据的代码,全部移到initAfterConversion
}

private void initAfterConversion() {
    // 示例:读取转换后的数据库数据、初始化UI组件
    loadConvertedData();
    setupAppUI();
}

方法二:使用AsyncTask(适合Java场景)

AsyncTask封装了线程切换逻辑,代码更简洁:

private class DataConvertTask extends AsyncTask<Void, Void, Void> {
    private AlertDialog loadingDialog;

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        // 显示加载对话框
        AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
        builder.setCancelable(false);
        builder.setView(R.layout.progress_dialog);
        loadingDialog = builder.create();
        loadingDialog.show();
    }

    @Override
    protected Void doInBackground(Void... voids) {
        // 后台执行数据转换
        db.convertData();
        return null;
    }

    @Override
    protected void onPostExecute(Void aVoid) {
        super.onPostExecute(aVoid);
        // 关闭对话框并执行后续逻辑
        loadingDialog.dismiss();
        initAfterConversion();
    }
}

在onCreate中启动任务:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    
    initDB();
    // 启动转换任务
    new DataConvertTask().execute();
}

额外优化:避免重复转换

如果转换只需在配置变更后执行一次,可用SharedPreferences记录状态,避免每次启动都重复转换:

private boolean needDataConversion() {
    SharedPreferences sp = getSharedPreferences("app_settings", MODE_PRIVATE);
    // 读取当前数字格式和已转换的格式标记
    String currentFormat = sp.getString("number_format", "default");
    String convertedFormat = sp.getString("converted_format", "");
    
    return !currentFormat.equals(convertedFormat);
}

// 转换完成后更新标记
private void markConversionComplete() {
    SharedPreferences sp = getSharedPreferences("app_settings", MODE_PRIVATE);
    String currentFormat = sp.getString("number_format", "default");
    sp.edit().putString("converted_format", currentFormat).apply();
}

在后台转换逻辑中加入判断:

@Override
protected Void doInBackground(Void... voids) {
    if (needDataConversion()) {
        db.convertData();
        markConversionComplete();
    }
    return null;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 02:17:10