【问题标题】:What is the fastest way to parse a JSON string into an SQLite table?将 JSON 字符串解析为 SQLite 表的最快方法是什么?
【发布时间】:2012-05-31 13:24:52
【问题描述】:

我正在编写一个 Android 应用程序,它偶尔需要下载一个大约 1MB 并包含大约 1000 个元素的 json 字符串,并将每个元素解析到一个 SQLite 数据库中,我用它来填充 ListActivity。

即使下载和解析不是每次与应用交互时都需要完成的事情(仅在首次运行或用户选择刷新数据时),我仍然担心解析部分是耗时太长,大约两到三分钟 - 从手机应用程序的角度来看,这似乎是永恒的!

我目前正在使用 Gson 将每个 json 对象解析为我定义的自定义对象,然后使用 SQLiteOpenHelper 将其输入数据库。

我的问题是 - 有没有更快的方法来实现这一点?在不使用 Gson 的情况下直接与 json 交互会明显更快吗?还是我在下面的代码中做了一些愚蠢的事情来减慢速度?

这是我在 AsyncTask 中使用的将 json 解析为 SQLite 的方法:

protected Boolean doInBackground(Integer... bType) {

    InputStream source = getJsonInputStream(bTypeString);

    VegDataHandler db = new VegDataHandler(mainActivity, bTypeString);
    Gson gson = new Gson();
    Reader reader = new InputStreamReader(source);

    JsonParser jParser = new JsonParser();
    JsonArray jArray = jParser.parse(reader).getAsJsonArray();

    aLength = jArray.size();
    mCurrProgress = 1;
    publishProgress(mCurrProgress, 0, aLength);

    /* Each array element is of the form { company: {...} } */
    int i = 0;
    mCurrProgress = 2;
    for (JsonElement obj : jArray) {
        Company c = gson.fromJson(obj.getAsJsonObject().getAsJsonObject("company"), Company.class);
        db.addCompany(c);
        i++;
        publishProgress(mCurrProgress, i);
    }
}

这是我的 VegDataHandler 类中的 addCompany 方法,它扩展了 SQLiteOpenHelper:

public void addCompany(Company c) {
    SQLiteDatabase db = this.getWritableDatabase();
    ContentValues values = new ContentValues();
    values.put(KEY_ID, c.getCompanyId());
    values.put(KEY_NAME, c.getCompanyName());
    values.put(KEY_RYG, c.getCompanyRedYellowGreen());
    values.put(KEY_COUNTRY, c.getCompanyCountry());
    values.put(KEY_URL, c.getCompanyUrl());
    values.put(KEY_NOTES, c.getCompanyNotes());
    values.put(KEY_EMAIL, c.getCompanyEmail());
    db.insertWithOnConflict(TABLE_COMPANY, null, values, SQLiteDatabase.CONFLICT_REPLACE);
    db.close();
}

这是在添加到 SQLite 之前保存每个 json 元素的类(为简洁起见,我省略了 getter 和 setter)。

public class Company {

    public Company() {
    }

    @SerializedName("id")
    public int companyId;

    @SerializedName("company_name")
    public String companyName;

    @SerializedName("red_yellow_green")
    public String companyRedYellowGreen;

    @SerializedName("country")
    public String companyCountry;

    @SerializedName("url")
    public String companyUrl;

    @SerializedName("notes")
    public String companyNotes;

    @SerializedName("email")
    public String companyEmail;

}

提前感谢您的任何回复。

【问题讨论】:

  • 您是否尝试过找出延迟的原因 - 是下载耗时还是解析耗时?
  • 是否要在数据库中添加批量记录?
  • @Rajesh - 绝对是解析花费的时间最多。我正在使用 publishProgress() 方法来显示它处于下载/解析/膨胀的哪个阶段。
  • @PareshMayani - 恐怕我不确定您所说的添加批量记录是什么意思?
  • 要尝试的一件事是保持数据库打开,直到插入所有记录。我的意思是,将SQLiteDatabase db = this.getWritableDatabase();db.close(); 语句移到addCompany 方法之外。

标签: android json sqlite gson sqliteopenhelper


【解决方案1】:

首先,您需要确定进程中占用时间最多的部分。从您上面的评论看来,JSON 解析是罪魁祸首。

如果 JSON 解析是问题:
研究并考虑更快的 JSON 解析器。也许像json-smart

如果 SQLite/DB 批量插入是问题所在:
See my answer here

一般提示:

  • 尽可能地回收对象(将new保持在最低限度)
  • 至少始终在 DB 批量插入中使用事务
  • 不要打开/关闭数据库。在处理开始/结束时执行一次
  • 使用预编译语句!

【讨论】:

  • 这很好,非常感谢您的提示。我将研究 json-smart 和 DB 批量插入,看看是否可以节省更多宝贵的时间!
猜你喜欢
  • 2012-07-28
  • 2017-04-25
  • 2013-03-08
  • 1970-01-01
  • 2017-02-03
  • 1970-01-01
  • 2021-04-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多