Android App停止响应SQLCipher

时间:2017-05-26 07:21:17

标签: android performance android-sqlite android-database sqlcipher-android

我刚刚将我的数据库从SQLite更改为SQLCipher。我的应用程序变得令人难以置信地缓慢。点击操作需要很长时间。 我研究并发现了这两个可能的原因:

  • 不要重复打开和关闭连接,因为密钥派生在设计上非常昂贵。经常打开/关闭数据库连接(例如,对于每个查询)是性能问题的一个非常常见的原因,通常可以使用单一数据库连接轻松解决。

  • 使用事务来包装插入/更新/删除操作。除非在事务范围内执行,否则每个操作都将在它自己的事务中发生,这会使事情减慢几个数量级。

关于第一点,有人可以通过反复打开和关闭连接来解释它是什么意思。我认为我对每个查询使用SQLiteDatabase db = this.getWritableDatabase("secure_key);都是问题所在。关于如何使用单例数据库连接类的任何示例都将是一个很好的帮助。

关于第二点,我如何为所提到的查询使用包装器并且它是否有用?

1 个答案:

答案 0 :(得分:0)

关于第1点),DBHelper内的以下代码创建了单例连接(注意我只关闭主活动的onDestroy方法中的数据库)。

/**
 * Instantiates a new Db helper.
 *
 * @param context the context
 */
DBHelper(Context context) {
    super(context, DBConstants.DATABASE_NAME, null, 1);
}

private static DBHelper instance;

/**
 * Gets helper.
 *
 * @param context the context
 * @return the helper
 */
static synchronized DBHelper getHelper(Context context) {
    if(instance == null) {
        instance = new DBHelper(context);
    }
    return instance;
}

并使用以下内容获取帮助: -

    dbhelper = DBHelper.getHelper(context);
    db = dbhelper.getWritableDatabase();

关于2,您使用db.beginTransaction();开始交易,db.setTransactionSuccessful();在更改数据库后将其标记为成功(这是为了应用交易所必需的否则,结束交易将有效地否定所应用的任何更改)和db.endTransaction();来完成交易。 请注意,事务不会嵌套,因此在嵌套事务时,您必须添加代码,以便beginTransactionsetTransactionSuccessfullendTransaction仅应用一次。

以下是一个适合嵌套的示例: -

 void deleteAisle(long aisleid, boolean intransaction) {

    if (doesAisleExist(aisleid)) {
        if (!intransaction) {
            db.beginTransaction();
        }

        String whereargs[] = {Long.toString(aisleid)};
        // Delete ProductUsage rows that have Aisle as a parent
        pudeletes = db.delete(
                DBProductusageTableConstants.PRODUCTUSAGE_TABLE,
                DBProductusageTableConstants.PRODUCTUSAGE_AISLEREF_COL +
                        " = ?",
                whereargs
        );

       // More done here but removed for brevity (including deletion of the Aisle)

        if (!intransaction) {
            db.setTransactionSuccessful();
            db.endTransaction();
            msg = "DB Transacion SET and ENDED for Aisle ID=" + Long.toString(aisleid);

        }
    }
}

以上可以单独调用,但是如果删除商店则可以多次调用,在这种情况下,调用** intransaction **为真(所以beginTransaction,{{1} }和setTransactionSuccessful将被跳过并由父母完成。

至于有用性,如果一起做多个动作,你只会使用交易。