You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何用新JSON值更新SQLite数据库(货币应用场景)

看起来你在给货币应用做SQLite数据库的JSON数据更新这块卡壳了,我来帮你捋捋思路,结合你的场景给出具体的解决方案~


核心需求拆解

你要实现的是:联网/汇率变动时用新JSON更新数据库,离线时读取本地缓存数据,核心难点在于如何把JSON数据高效、正确地同步到SQLite,同时区分更新/读取场景。

第一步:先明确数据库表结构(关键前提)

假设你的表用来存储货币基础信息和汇率,建议给每个货币加唯一标识(比如货币编码currency_code),方便后续自动判断是新增还是更新:

CREATE TABLE IF NOT EXISTS currency_info (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    currency_code TEXT UNIQUE NOT NULL, -- 比如USD、EUR,作为唯一键
    name TEXT NOT NULL,
    description TEXT,
    exchange_rate REAL NOT NULL,
    last_update TIMESTAMP DEFAULT CURRENT_TIMESTAMP -- 记录更新时间,方便判断数据时效性
);

第二步:实现「JSON更新数据库」的核心方法

利用SQLite的INSERT OR REPLACE特性,自动处理“新增货币”和“更新已有货币汇率”的场景,同时用事务提升批量更新的性能:

private void updateCurrencyFromJson(SQLiteDatabase db, JSONObject newCurrencyJson) throws JSONException {
    // 对应你的JSON字段(根据实际结构调整)
    final String MNU_CODE = "currency_code";
    final String MNU_NAME = "name";
    final String MNU_DESCRIPTION = "description";
    final String MNU_RATE = "exchange_rate";

    // 假设你的JSON是包含多个货币的数组,若为单个对象则直接解析即可
    JSONArray currencyArray = newCurrencyJson.getJSONArray("currencies");

    // 开启事务,避免批量更新时多次IO操作
    db.beginTransaction();
    try {
        ContentValues values = new ContentValues();
        for (int i = 0; i < currencyArray.length(); i++) {
            JSONObject currencyObj = currencyArray.getJSONObject(i);
            
            values.put("currency_code", currencyObj.getString(MNU_CODE));
            values.put("name", currencyObj.getString(MNU_NAME));
            // 用optString避免字段缺失导致崩溃
            values.put("description", currencyObj.optString(MNU_DESCRIPTION, ""));
            values.put("exchange_rate", currencyObj.getDouble(MNU_RATE));
            values.put("last_update", System.currentTimeMillis());

            // 关键:根据唯一键currency_code自动判断新增/更新
            db.insertWithOnConflict("currency_info", null, values, SQLiteDatabase.CONFLICT_REPLACE);
        }
        db.setTransactionSuccessful(); // 事务成功,提交更改
    } finally {
        db.endTransaction(); // 无论成功失败,都结束事务
    }
}

第三步:实现「离线读取缓存数据」的方法

从数据库读取旧数据并重新组装成JSON格式,方便业务层直接使用:

private JSONObject getCachedCurrencyData(SQLiteDatabase db) throws JSONException {
    JSONObject resultJson = new JSONObject();
    JSONArray currencyArray = new JSONArray();

    Cursor cursor = db.query("currency_info", null, null, null, null, null, "currency_code ASC");
    try {
        while (cursor.moveToNext()) {
            JSONObject currencyObj = new JSONObject();
            currencyObj.put("currency_code", cursor.getString(cursor.getColumnIndex("currency_code")));
            currencyObj.put("name", cursor.getString(cursor.getColumnIndex("name")));
            currencyObj.put("description", cursor.getString(cursor.getColumnIndex("description")));
            currencyObj.put("exchange_rate", cursor.getDouble(cursor.getColumnIndex("exchange_rate")));
            currencyObj.put("last_update", cursor.getLong(cursor.getColumnIndex("last_update")));
            
            currencyArray.put(currencyObj);
        }
        resultJson.put("currencies", currencyArray);
    } finally {
        cursor.close(); // 务必关闭Cursor,避免内存泄漏
    }
    return resultJson;
}

第四步:业务层调用逻辑(结合网络状态)

在你的应用业务代码里,判断网络状态或是否需要更新汇率,选择更新或读取缓存:

// 假设你有判断网络是否可用的工具方法
if (NetworkUtils.isNetworkAvailable(context)) {
    // 1. 从接口获取最新汇率JSON
    JSONObject latestRatesJson = fetchLatestRatesFromApi();
    // 2. 更新数据库
    updateCurrencyFromJson(db, latestRatesJson);
    // 3. 使用最新数据
    renderCurrencyData(latestRatesJson);
} else {
    // 读取本地缓存数据
    JSONObject cachedData = getCachedCurrencyData(db);
    renderCurrencyData(cachedData);
}

踩坑提醒

  • JSON字段兼容性:尽量用optString/optDouble替代getString/getDouble,避免JSON字段缺失导致崩溃
  • 事务必须正确使用:批量更新时一定要用事务,否则不仅性能差,还可能出现部分数据更新失败的情况
  • 唯一键必须设置:没有唯一键的话,INSERT OR REPLACE会变成重复插入,无法实现更新逻辑
  • Cursor务必关闭:读取数据后一定要关闭Cursor,否则会造成内存泄漏

如果你的readDataToDb是用来初始化数据库(比如第一次启动时读取本地预设的JSON文件),可以在应用首次启动时调用一次,之后就用上面的updateCurrencyFromJson来处理后续的更新需求啦~

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

火山引擎 最新活动