【发布时间】:2016-07-05 21:15:50
【问题描述】:
我的应用预装了三个数据库。一个很大,有 293,092 行,其中大部分是长句子。我的问题是每当我在工作线程中查询(rawQuery)大的时,UI 可能会冻结 1 秒。
这是我的查询语句:
SELECT verse
FROM Translations
WHERE translatorId = ?
AND chapterNbr = ?
AND verseNbr BETWEEN ? AND ?
ORDER BY chapterNbr , verseNbr
这里的问题是即使我故意只查询 1 行(1 个结果),UI 仍然冻结。
请帮忙。非常感谢。
这是我很长的代码:
static void setVerseAdapter(final int[][] refs) {
surahThread = new Thread(new Runnable() {
@Override
public void run() {
Cursor cursor = Translations.getTranslators();
final int[] translationIds = new int[cursor.getCount()];
while (cursor.moveToNext()) {
translationIds[cursor.getPosition()] = cursor.getInt(0);
}
adapterVerses = new AdapterVerses
(context, getVersesArray(refs), Translations.getTranslationsArray(translationIds, refs)); // this one is the problem, the getTranslationsArray
// remaining code in this method is irrelevant ...
});
surahThread.start();
}
static Cursor[][] getTranslationsArray(int[] translationIds, int[]... refs) {
if (!Settings.showTranslation)
return new Cursor[][]{{}};
Cursor[][] translations = new Cursor[refs.length][];
for (int i = 0; i < refs.length; i++) {
int start = refs[i][0];
int end = refs[i][1];
int surahNbr = refs[i][2];
translations[i] = getTranslations(translationIds, start, end, surahNbr);
}
return translations;
}
static Cursor[] getTranslations(int[] translatorIds, int start, int end, int surahNbr) {
Cursor[] translations = new Cursor[translatorIds.length];
for (int i = 0; i < translatorIds.length; i++) {
translations[i] = readTrans(
"SELECT verse " +
"FROM Translations " +
"WHERE translatorId = ? " +
"AND surahNbr = ? " +
"AND verseNbr BETWEEN ? AND ? " +
"ORDER BY surahNbr, verseNbr",
translatorIds[i], surahNbr + 1, start, end
);
}
return translations;
}
static Cursor readTrans(String query, Object... args) {
SQLiteDatabase transDb = transExists ? DB.trans.db : DB.user.db; // using user.db results to no freezing
return transDb.rawQuery(replaceArgs(query, args), null);
}
当我使用 DB.user.db 而不是 DB.trans.db 时,上面的一切都可以正常工作。 它们之间的区别在于它们的大小。第一个只有 ~4MB,第二个(有问题的)在解压后约为 65MB。
谢谢。
【问题讨论】:
-
请提供minimal reproducible example。这将包括您查询数据库的代码和您使用从查询返回的
Cursor的代码。 -
我已经更新了我的问题。谢谢。
-
你的代码……令人费解。您还在快速连续地进行大量查询,这通常会导致性能下降。特别是关于线程,请确保您对每个
Cursor执行操作,当您在后台线程上时 从数据库返回。query()和rawQuery()等方法实际上并不执行查询。他们设置了Cursors,但直到您实际使用Cursor(惰性评估)执行某些操作时才完成查询。如果不出意外,请致电getCount()。 -
你测量时间了吗?我敢打赌,问题出在适配器本身...我敢打赌,您使用了一种愚蠢的解决方案来在可滚动的内部滚动,从而避免在列表视图中重复使用正确的视图
-
我的最后一次编辑... [当我使用 DB.user.db 而不是 DB.trans.db 时,上面的一切都可以正常工作。它们之间的区别在于它们的大小。第一个只有约 4MB,第二个(有问题的)在解压后约为 65MB。] ... 除了完全重构我的代码之外,您还能想出另一种解决方案吗?也许关于上面的陈述?谢谢。
标签: java android database multithreading sqlite