我的Google Play开发者控制台报告了我的Android应用程序首次崩溃。看起来SQLite无法为光标分配内存,但我以前从未见过它并且无法重现它。有任何想法吗?
谷歌报道的Stackgrace:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.NsouthProductions.gradetrackerpro/com.NsouthProductions.gradetrackerpro.Activity_Category}: android.database.CursorWindowAllocationException: Cursor window allocation of 2048 kb failed. # Open Cursors=530 (# cursors opened by this proc=530)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2305)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2363)
at android.app.ActivityThread.access$900(ActivityThread.java:161)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1265)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:157)
at android.app.ActivityThread.main(ActivityThread.java:5356)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
at dalvik.system.NativeStart.main(Native Method)
Caused by: android.database.CursorWindowAllocationException: Cursor window allocation of 2048 kb failed. # Open Cursors=530 (# cursors opened by this proc=530)
at android.database.CursorWindow.<init>(CursorWindow.java:108)
at android.database.CursorWindow.<init>(CursorWindow.java:100)
at android.database.AbstractWindowedCursor.clearOrCreateWindow(AbstractWindowedCursor.java:198)
at android.database.sqlite.SQLiteCursor.clearOrCreateWindow(SQLiteCursor.java:301)
at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:139)
at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:133)
at android.database.AbstractCursor.moveToPosition(AbstractCursor.java:197)
at android.database.AbstractCursor.moveToFirst(AbstractCursor.java:237)
at com.NsouthProductions.gradetrackerpro.DBAdapter.getCourse(DBAdapter.java:401)
at com.NsouthProductions.gradetrackerpro.Activity_Category$CategoryActivityFragment.setListData(Activity_Category.java:196)
at com.NsouthProductions.gradetrackerpro.Activity_Category$CategoryActivityFragment.onCreateView(Activity_Category.java:182)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:1500)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:938)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1115)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1478)
at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:570)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1189)
at android.app.Activity.performStart(Activity.java:5436)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278)
... 11 more
我的DBAdapter类失败的地方。
public Course getCourse (int rowId) throws SQLException {
Cursor c =
db.query(true, TABLE_COURSES, new String[] {KEY_ID, KEY_TITLE,
KEY_YEAR, KEY_SEASON, KEY_CREDIT}, KEY_ID + "=" + rowId, null, null, null, null, null);
if (c != null) {
c.moveToFirst();
}
Course course = new Course(c.getInt(0), c.getString(1), c.getInt(2), c.getString(3), c.getDouble(4));
return course;
}
调用DBAdapter函数的位置。在活动的这一点上,数据库已经成功打开,查询和关闭。
public void setListData(){
db.open();
Grade[] g = db.getGradesInCategory(catId);
this.getActivity().setTitle(db.getCourse(courseId).getTitle());
db.close();
答案 0 :(得分:7)
实际上是OutOfMemoryError
。引用the comments for that exception class:
当无法分配CursorWindow时抛出此异常,很可能是因为内存不可用。
错误消息显示您有530个打开的Cursor
个对象,这可能是您问题的一部分。例如,您在Cursor
方法中泄漏getCourse()
。确保在完成后立即关闭Cursor
。
如果这没有帮助,您需要将其视为OutOfMemoryError
,并确定您在哪里浪费堆空间,可能是using tools like MAT。
答案 1 :(得分:1)
游标需要关闭:
Cursor c = db.query(...);
try {
...
} finally {
c.close();
}
答案 2 :(得分:1)
如果您不想使用多个局部变量进行返回,则可以返回Cursor对象,然后从调用方法中将其关闭。
这是对#34;的响应。嗯。有时我使用return cursor.getString(0)。我想我不能在返回后关闭光标,也不能在关闭后使用它。我必须返回临时变量,对吧? - NSouth Oct 4&#39; 14 at 20:44:&amp;
@NSouth:&#34;我必须返回临时变量,对吗?&#34; - 如果你的意思是局部变量(在方法体中声明的东西),那么是的。 - CommonsWare 10月4日和14日在20:46
我知道这更像是一个评论,然后是答案,但我没有评论的声誉点,并认为这可能会有所帮助。