标准ORMLite方法中的CursorWindowAllocationException

Wis*_*ter 7 sql android cursor ormlite

我需要在DB中保存一些对象.我在我的Dao课程中使用此代码.

  public void saveActions(List<Action> actionList) throws SQLException {
    for (Action action : actionList) {
        createOrUpdate(action);
      }
  }
Run Code Online (Sandbox Code Playgroud)

有时我在createOrUpdate()函数中有CursorWindowAllocationException .

这是错误的堆栈跟踪.

java.lang.RuntimeException:在java. java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)的android.os.AsyncTask $ 3.done(AsyncTask.java:300)上执行doInBackground()时发生错误. util.concurrent.FutureTask.setException(FutureTask.java:222)at java.util.concurrent.FutureTask.run(FutureTask.java:242)at android.os.AsyncTask $ SerialExecutor $ 1.run(AsyncTask.java:231)at at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)java.lang.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor.java:587)java.lang.Thread.run(Thread.java:841)引起:android.database.CursorWindowAllocationException:游标窗口分配2048 kb失败.在android.database.CursorWindow.(CursorWindow.java:109)的android.database.CursorWindow.(CursorWindow.java:100)在android.database.AbstractWindowedCursor.clearOrCreateWindow(AbstractWindowedCursor.java:198)的android.database.sqlite.在android.database.AbstractCursor的android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:133)的android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:139)上的SQLiteCursor.clearOrCreateWindow(SQLiteCursor.java:301) .moveToPosition(AbstractCursor.java:197)位于com.j256.ormlite.android的com.j256.ormlite.android.AndroidDatabaseResults.first(SourceFile:73)的android.database.AbstractCursor.moveToFirst(AbstractCursor.java:237). com.j256.ormlite.st上的com.j256.ormlite.stmt.StatementExecutor.ifExists(SourceFile:603)的com.j256.ormlite.dao.BaseDaoImpl.idExists(SourceFile:807)中的AndroidDatabaseConnection.queryForLong(SourceFile:234),com.j256.ormlite.dao .BaseDaoImpl.createOrUpdate(SourceFile:335)at com.deliveryclub.command.db.SaveActionsCommand.execute(Sourc)eFile:11)在ru.surfstudio.command.CommandExecutor.executeCommand(SourceFile:34)at ru.surfstudio.background.CommonAsyncTask.doInBackground(SourceFile:10)at android.os.AsyncTask $ 2.call(AsyncTask.java:288)在java.util.concurrent.FutureTask.run(FutureTask.java:237)... 4 more android.database.CursorWindowAllocationException:2048 kb的游标窗口分配失败.在android.database.CursorWindow.(CursorWindow.java:109)的android.database.CursorWindow.(CursorWindow.java:100)在android.database.AbstractWindowedCursor.clearOrCreateWindow(AbstractWindowedCursor.java:198)的android.database.sqlite.在android.database.AbstractCursor的android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:133)的android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:139)上的SQLiteCursor.clearOrCreateWindow(SQLiteCursor.java:301) .moveToPosition(AbstractCursor.java:197)位于com.j256.ormlite.android的com.j256.ormlite.android.AndroidDatabaseResults.first(SourceFile:73)的android.database.AbstractCursor.moveToFirst(AbstractCursor.java:237). com.j256.ormlite.st上的com.j256.ormlite.stmt.StatementExecutor.ifExists(SourceFile:603)的com.j256.ormlite.dao.BaseDaoImpl.idExists(SourceFile:807)中的AndroidDatabaseConnection.queryForLong(SourceFile:234),com.j256.ormlite.dao .BaseDaoImpl.createOrUpdate(SourceFile:335)at com.deliveryclub.command.db.SaveActionsCommand.execute(Sourc)eFile:11)在ru.surfstudio.command.CommandExecutor.executeCommand(SourceFile:34)at ru.surfstudio.background.CommonAsyncTask.doInBackground(SourceFile:10)at android.os.AsyncTask $ 2.call(AsyncTask.java:288)在java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java)的android.os.AsyncTask $ SerialExecutor $ 1.run(AsyncTask.java:231)中的java.util.concurrent.FutureTask.run(FutureTask.java:237) 1112)java.lang.Thread.run上的java.util.concurrent.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor.java:587)(Thread.java:841)

UPD Action类

  @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;
    }
Run Code Online (Sandbox Code Playgroud)

有没有人解决这个问题?

Pau*_*rke 2

如果你查一下它的来源,CursorWindowAllocationException它是这样写的:

当无法分配 CursorWindow 时会引发此异常,很可能是由于内存不可用。

如果您跟踪堆栈,您将看到该调用com.j256.ormlite.android.AndroidDatabaseConnection.queryForLong正在为每个调用创建一个游标createOrUpdate

Cursors所以这里可能发生的情况是在释放内存之前创建了太多的内存。

您应该在事务中执行这些调用,或者更好的是,使用批处理任务。例如

actionDao.callBatchTasks(new Callable<Void>() {
        public Void call() throws SQLException {
            for (Action action : actionList) {
                actionDao.createOrUpdate(action);
            }
        return null;
    }
});
Run Code Online (Sandbox Code Playgroud)