SQLite Android数据库光标窗口分配2048 kb失败
我有一个例程每秒多次对SQLite数据库运行不同的查询。 过了一段时间,我会得到错误
"android.database.CursorWindowAllocationException: - Cursor window allocation of 2048 kb failed. # Open Cursors = "
出现在LogCat中。
我有应用程序日志内存使用情况,实际上,当使用量达到一定的限制,我得到这个错误,意味着它用完了。 我的直觉告诉我,每次运行查询时,数据库引擎都会创build一个新的缓冲区(CursorWindow),即使我标记了.close()游标,垃圾收集器和SQLiteDatabase.releaseMemory()
释放记忆。 我认为解决scheme可能在于“迫使”数据库始终写入相同的缓冲区,而不是创build新的数据库,但我一直无法find办法做到这一点。 我试图实例化我自己的CursorWindow,并试图设置它和SQLiteCursor无济于事。
有任何想法吗?
编辑:重新从@GrahamBorland示例代码请求:
public static CursorWindow cursorWindow = new CursorWindow("cursorWindow"); public static SQLiteCursor sqlCursor; public static void getItemsVisibleArea(GeoPoint mapCenter, int latSpan, int lonSpan) { query = "SELECT * FROM Items"; //would be more complex in real code sqlCursor = (SQLiteCursor)db.rawQuery(query, null); sqlCursor.setWindow(cursorWindow); }
理想情况下,我希望能够.setWindow()
之前提供一个新的查询,并将数据放入相同的CursorWindow
每当我得到新的数据。
大多数情况下,这个错误的原因是非closures的游标。 确保在使用完游标后closures所有游标(即使出现错误)。
Cursor cursor = null; try { cursor = db.query(... // do some work with the cursor here. } finally { // this gets called even if there is an exception somewhere above if(cursor != null) cursor.close(); }
如果您不得不深入研究大量的SQL代码,则可以通过将以下代码片段放在MainActivity中来启用StrictMode来加快debugging速度。 如果检测到泄露的数据库对象,那么您的应用程序现在会崩溃,日志信息突出显示您的泄漏的确切位置。 这帮助我在几分钟内find一个stream氓光标。
@Override protected void onCreate(Bundle savedInstanceState) { if (BuildConfig.DEBUG) { StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder() .detectLeakedSqlLiteObjects() .detectLeakedClosableObjects() .penaltyLog() .penaltyDeath() .build()); } super.onCreate(savedInstanceState); ... ...
我刚刚遇到过这个问题,并且在有效期间不closures游标的build议答案不是我如何修复它的。 我的问题是当SQLite试图重新填充它的游标时closures数据库。 我将打开数据库,查询数据库以获取游标到数据集,closures数据库并遍历游标。 我注意到每当我在该游标中点击某个logging时,我的应用程序就会在OP中出现同样的错误。
我假设游标访问某些logging,它需要重新查询数据库,如果它closures,它会抛出这个错误。 我解决了这个问题,直到完成了我所需要的所有工作。