Search code examples
androidandroid-roomandroid-9.0-pie

Android 9(only observed) using Room(for non-images): Row too big to fit into CursorWindow requiredPos=0, totalRows=1


I've only observed this on Android 9 and possibly only on Samsung devices. I'm storing multiple JSON responses to multiple serialized strings into my DB later to be typeConverted using Moshi again into a model.

The query that causes this error is:

@Query(“SELECT * FROM tasks”)
public abstract Flowable<List<TaskEntity>> getAll();

The last instance had a total of about 392,000 characters TOTAL in the table. These are actually split up into about 5500 character size entries within the table.

  1. Why would the cursor have a problem with ~11k byte sized entries? Does the fact that I'm selecting * mean the cursor is grabbing the whole table into memory and not a single row at a time?
  2. Why only Android 9?

Thanks.


Solution

  • Does the fact that I'm selecting * mean the cursor is grabbing the whole table into memory and not a single row at a time?

    SELECT * means you are retrieving all columns. A SELECT without a WHERE clause (or other types of constraints) means that you are retrieving all rows. So, SELECT * FROM tasks will attempt to retrieve the entire table contents into memory.

    You could add @Transaction to this function, as that may help get past this error. Quoting the documentation:

    When used on a Query method that has a SELECT statement, the generated code for the Query will be run in a transaction. There are 2 main cases where you may want to do that:

    • If the result of the query is fairly big, it is better to run it inside a transaction to receive a consistent result. Otherwise, if the query result does not fit into a single CursorWindow, the query result may be corrupted due to changes in the database in between cursor window swaps.
    • If the result of the query is a POJO with Relation fields, these fields are queried separately. To receive consistent results between these queries, you also want to run them in a single transaction.

    Even better would be to not load the entire table's content's into memory (and then convert the entire table's rows into entity objects). Heap space is limited.

    Why only Android 9?

    No clue. I wouldn't worry about that — if you focus on retrieving less data, that will have benefits for all your users.