CursorWindowAllocationException in the standard ORMLite method

I need to save some objects in a DB. I use this code in my Dao class.

public void saveActions(List<Action> actionList) throws SQLException { for (Action action : actionList) { createOrUpdate(action); } } 

And sometimes I have a CursorWindowAllocationException function in createOrUpdate() .

Here are the stacktrace errors.

java.lang.RuntimeException: An error occurred during the execution of doInBackground () at android.os.AsyncTask $ 3.done (AsyncTask.javahaps00) in java.util.concurrent.FutureTask.finishCompletion (FutureTask.javahaps55) in java. util.concurrent.FutureTask.setException (FutureTask.java:222) in java.util.concurrent.FutureTask.run (FutureTask.java:242) at android.os.AsyncTask $ SerialExecutor $ 1.run (AsyncTask.java:231) in java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1112) in java.util.concurrent.ThreadPoolExecutor $ Worker.run (ThreadPoolExecutor.javahaps87) in java.lang.Thread.run (Thread.java:841) Called: android.database.CursorWindowAllocationException: Failed to select cursor window 2048 kb. in android.database.CursorWindow. (CursorWindow.java:109) in android.database.CursorWindow. (CursorWindow.java:100) in android.database.AbstractWindowedCursor.clearOrCreateWindow (AbstractWindowedCursor.java:198) in android.database.sqlite.SQLiteCursor.clearOrCreateWindow (SQLiteCursor.javahaps01 )l.iteSQLWillow.l SQLiteCursor.java:139) on android.database.sqlite.SQLiteCursor.getCount (SQLiteCursor.java:133) in android.database.AbstractCursor.moveToPosition (AbstractCursor.java:197) in android.database.AbstractCursor.moveToFirst (AbstractCursor : 237) at com.j256.ormlite.android.AndroidDatabaseResults.first (SourceFile: 73) at com.j256.ormlite.android.AndroidDatabaseConnection.queryForLong (SourceFile: 234) at com.j256.ormlite.stmt.StatementExecutor.ifExists ( SourceFile: 603) at com.j256.ormlite.dao.BaseDaoImpl.idExists (SourceFile: 807) at com.j256.ormlite.dao.BaseDaoImpl.createOrUpdate (SourceFile: 335) at com.deliveryclub.command.db.SaveActionsCommandexecute (SourceFile: 11) on ru.surfstudio .command.CommandExecutor.executeCommand (SourceFile: 34) at ru.surfstudio.background.CommonAsyncTask.doInBackground (SourceFile: 10) at android.os.AsyncTask $ 2.call (AsyncTask.java:288) in java.util.concurrent.Future .run (FutureTask.java:237) ... 4 more android.database.CursorWindowAllocationException: Failed to select cursor window 2048 kb. in android.database.CursorWindow. (CursorWindow.java:109) in android.database.CursorWindow. (CursorWindow.java:100) in android.database.AbstractWindowedCursor.clearOrCreateWindow (AbstractWindowedCursor.java:198) in android.database.sqlite.SQLiteCursor.clearOrCreateWindow (SQLiteCursor.javahaps01 )l.iteSQLWillow.l SQLiteCursor.java:139) on android.database.sqlite.SQLiteCursor.getCount (SQLiteCursor.java:133) in android.database.AbstractCursor.moveToPosition (AbstractCursor.java:197) in android.database.AbstractCursor.moveToFirst (AbstractCursor : 237) at com.j256.ormlite.android.AndroidDatabaseResults.first (SourceFile: 73) at com.j256.ormlite.android.AndroidDatabaseConnection.queryForLong (SourceFile: 234) at com.j256.ormlite.stmt.StatementExecutor.ifExists ( SourceFile: 603) at com.j256.ormlite.dao.BaseDaoImpl.idExists (SourceFile: 807) at com.j256.ormlite.dao.BaseDaoImpl.createOrUpdate (SourceFile: 335) at com.deliveryclub.command.db.SaveActionsCommandexecute (SourceFile: 11) on ru.surfstudio .command.CommandExecutor.executeCommand (SourceFile: 34) at ru.surfstudio.background.CommonAsyncTask.doInBackground (SourceFile: 10) at android.os.AsyncTask $ 2.call (AsyncTask.java:288) in java.util.concurrent.Future .run (FutureTask.java:237) at android.os.AsyncTask $ SerialExecutor $ 1.run (AsyncTask.java:231) in java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1112) in java.util.concurrent .ThreadPoolExecutor $ Worker.run (ThreadPoolExecutor.java//87) in java.lang.Thread.run (Thread.java:841)

UPD Action Class

  @SuppressWarnings("serial") @DatabaseTable(tableName = "Action") public class Action implements Serializable { public static final String SERVICE_ID = "SERVICE_ID"; public static final String CITY_ID = "CITY_ID"; public static final String CATEGORY_ID = "CATEGORY_ID"; public static final String TITLE = "TITLE"; public static final String SERVICE_TITLE = "SERVICE_TITLE"; public static final String DESCRIPTION = "DESCRIPTION"; public static final String DEADLINE = "DEADLINE"; public static final String PERCENTAGE = "PERCENTAGE"; public static final String PICTURE_URL = "PICTURE_URL"; @DatabaseField(columnName = SERVICE_ID, id = true, useGetSet = true) private int serviceId; @DatabaseField(columnName = CITY_ID, useGetSet = true) private int cityId; @DatabaseField(columnName = CATEGORY_ID, useGetSet = true) private int categoryId; @DatabaseField(columnName = TITLE, useGetSet = true) private String title; @DatabaseField(columnName = SERVICE_TITLE, useGetSet = true) private String serviceTitle; @DatabaseField(columnName = DESCRIPTION, useGetSet = true) private String description; @DatabaseField(columnName = DEADLINE, useGetSet = true) private Date deadline; @DatabaseField(columnName = PERCENTAGE, useGetSet = true) private int percentage; @DatabaseField(columnName = PICTURE_URL, useGetSet = true) private String pictureUrl; public Action() { } public int getServiceId() { return serviceId; } public void setServiceId(int serviceId) { this.serviceId = serviceId; } public int getCityId() { return cityId; } public void setCityId(int cityId) { this.cityId = cityId; } public int getCategoryId() { return categoryId; } public void setCategoryId(int categoryId) { this.categoryId = categoryId; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getServiceTitle() { return serviceTitle; } public void setServiceTitle(String serviceTitle) { this.serviceTitle = serviceTitle; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public Date getDeadline() { return deadline; } public void setDeadline(Date deadline) { this.deadline = deadline; } public int getPercentage() { return percentage; } public void setPercentage(int percentage) { this.percentage = percentage; } public String getPictureUrl() { return pictureUrl; } public void setPictureUrl(String pictureUrl) { this.pictureUrl = pictureUrl; } 

Anyone have a solution to this problem?

+7
android sql cursor ormlite
source share
2 answers

If you look at the source of CursorWindowAllocationException , it reads:

This exception is thrown when CursorWindow cannot be allocated, most likely due to inaccessible memory.

If you follow the stack, you will see that a call to com.j256.ormlite.android.AndroidDatabaseConnection.queryForLong creates a cursor for each call to createOrUpdate .

So, probably, what happens here is that too many Cursors are Cursors before the memory is freed.

You must complete these calls in transaction , or even better, use batch tasks . For example.

 actionDao.callBatchTasks(new Callable<Void>() { public Void call() throws SQLException { for (Action action : actionList) { actionDao.createOrUpdate(action); } return null; } }); 
+2
source share

You must call cursor.close(); into the finally {} block when you no longer need a cursor. The selection of the cursor will fail, not calling close () on the cursor after a while, when the system resources for placing the cursor are unavailable.

-one
source share

All Articles