Android 9(仅观察到)使用 Room(对于非图像):行太大而无法放入 CursorWindow requiredPos=0,totalRows=1

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

我只在 Android 9 上观察到这一点,而且可能只在三星设备上观察到过。我将对多个序列化字符串的多个 JSON 响应存储到我的数据库中,稍后再次使用 Moshi 将类型转换为模型。

导致此错误的查询是:

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

最后一个实例在 table 中共有约 392,000 个字符。这些实际上在 table.

中分成大约 5500 个字符大小的条目
  1. 为什么游标对 ~11k 字节大小的条目有问题?我选择 * 是否意味着光标将整个 table 抓取到内存中,而不是一次抓取一行?
  2. 为什么只有 Android 9 个?

谢谢。

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 * 表示您正在检索所有列。没有 WHERE 子句(或其他类型的约束)的 SELECT 意味着您正在检索所有行。因此,SELECT * FROM tasks 将尝试将整个 table 内容检索到内存中。

您可以将 @Transaction 添加到此函数,因为这可能有助于解决此错误。引用 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.

更好的做法是不要将整个 table 的内容加载到内存中(然后将整个 table 的行转换为实体对象)。堆 space 是有限的。

Why only Android 9?

没有线索。我不会担心这一点 — 如果您专注于检索更少的数据,那将对您的所有用户都有好处。