【问题标题】:Increase the performance of storing a JSON stream to a local database on Android提高在 Android 上将 JSON 流存储到本地数据库的性能
【发布时间】:2017-02-13 20:30:12
【问题描述】:

我正在开发一个应用程序,该应用程序(其部分功能)从服务器获取大量 JSON 格式的项目列表,并将其存储在本地 SQLite 数据库中。由于 JSON 文件很大,我使用 Gson 库来执行提取,否则应用程序会因为内存不足而崩溃。因此,我唯一的选择是将文件作为流获取。

JSON 文件结构类似这样:

{
  "items": [
    {
        "itemID": "id1",
        "itemName": "name1"
    },
    {
        "itemID": "id2",
        "itemName": "name2"
    }
  ]
}

我处理流的 Java 代码如下所示:

JsonReader reader = new JsonReader(url_buffered_reader);
reader.beginObject();

String itemId = null;
String itemName = null;

while (reader.hasNext()) {
    if (reader.nextName().equals("items")) {
        reader.beginArray();
        while (reader.hasNext()) {
            reader.beginObject();
            while (reader.hasNext()) {
                String name = reader.nextName();
                switch (name) {
                    case "itemID":
                        itemId = reader.nextString().trim();
                        break;
                    case "itemName":
                        itemName = reader.nextString().trim();
                        break;
                    default:
                        reader.skipValue();
                        break;
                }
            }
            reader.endObject();

            storeItemData(itemId, itemName);
        }
        reader.endArray();
    }
}

函数storeItemData(String id, String name) 看起来像这样(它在一个扩展SQLiteOpenHelper 的类中):

public void storeItemData(String id, String name) {
    SQLiteDatabase db = this.getWritableDatabase();

    ContentValues values = new ContentValues();
    values.put("itemID", id);
    values.put("itemName", name);

    long newRowId = db.insertWithOnConflict(
            "items",
            null,
            values, SQLiteDatabase.CONFLICT_REPLACE);
}

代码运行良好。数据已成功下载并存储。问题是性能不好。有没有更高效的方式来存储数据,从而提升性能?

【问题讨论】:

    标签: java android json performance sqlite


    【解决方案1】:

    将记录插入数据库会产生开销。假设数据库是您的瓶颈,您应该能够通过将插入包装到事务中来提高写入性能。

    1. SQLiteDatabase db = this.getWritableDatabase(); 移出storeItemData
    2. 在开始插入之前,请致电 db.beginTransaction();
    3. 插入完成后拨打db.setTransactionSuccessful();,然后拨打db.endTransaction();
    4. 请务必捕获所有异常,以便您可以优雅地处理插入可能导致的任何错误。

    【讨论】:

    • 谢谢!我实际上是在做第一个,但我将它移到了函数中,这样我就不必复制粘贴大量不必要的代码。关于db.beginTransaction();db.endTransaction();,我应该将它们放在JSON 循环之前和之后吗?据我了解,当达到db.endTransaction(); 时,他们将提交所有内容,而不是为每条记录都提交,对吗?
    • 循环前后应该可以正常工作,只要您在两者之间执行所有storeItemData 调用。是的,当达到endTransaction 时,您的所有插入都将提交。
    • 这正是我所希望的!我什至可以在网络监视器上看到连接是稳定的,而在它停止每秒保存数据之前再次感谢。
    • 给任何可能觉得这篇文章有用的人的注意事项:在db.endTransaction() 之前,您需要db.setTransactionSuccessful();。否则不会存储任何数据。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多