我创建了一个由查询返回的数据填充的ListView。
这是可行的,但在LogCat中我得到了这样的信息:
Cursor Window: Window is full: requested allocation 444 bytes, free space 363 bytes, window size 2097152 bytes它使用几分钟来加载/可视化ListView。
我的查询返回大约3700行字符串/Int/Double,每个行都有30列;没有图像或特定的数据类型
这条信息到底意味着什么?我如何避免它?
你能通过改变这个光标窗口来提高性能吗?
发布于 2014-07-08 09:38:22
根据我的经验,这意味着查询结果对于游标的窗口来说太大了,它需要更多的内存。大多数情况下,这个请求都会得到响应,但是在低端设备上,它可能会引发异常。
我不知道这个应用程序的具体细节,但是你提到了一个ListView。ListView不能同时显示3700行,endless list可以帮助按需加载数据。
我的建议是将查询分解为返回较小结果的多个查询,并在运行下一个查询之前关闭它们。每次连续查询后,组合结果。
发布于 2018-09-25 20:11:51
简写版:
经过一些调查后,这条信息似乎是正常运作的一部分,而不是一个值得关注的问题。它被记录在“警告”级别上,但我认为这是太迫切了。
更长版本:
这是(明确标记为)一个“窗口”游标,这意味着旧的记录将被丢弃,因为新的记录被获得。在最简单的形式中,这样的“窗口”实现可能包含最多N行总数,可能包含一些预读。但是,在此实现中,窗口大小由总大小来定义。相反,保存在内存中的行数取决于在整个窗口中容纳多少行,并且在运行时会有所不同(这可能更像是一个“缓冲”游标而不是“窗口”游标)。
作为具有(软?)上限大小的缓冲实现,只有当缓冲区太满,无法容纳下一行时,才会丢弃最早的行。在这种情况下,将删除一个或多个旧行。“根据需要继续分配行,直到我们不能再有更多的空间,此时我们释放缓冲区中最古老的记录,然后再试一次”进程似乎是完全正常和预期的,这是进程的正常部分,以保持内存空间的限制。
我把这个结论建立在阅读这里的源代码的基础上,并结合一些推论:https://android.googlesource.com/platform/frameworks/base/+/master/libs/androidfw/CursorWindow.cpp
为什么人们谈论图像和其他巨大的LOB?
如果单个行的大小大于整个“窗口”(缓冲区),则此策略将崩溃,您将遇到实际问题。
这就是@op收到的信息:
Cursor Window: Window is full: requested allocation 444 bytes, free space 363 bytes, window size 2097152 bytes这是@vovahost收到的信息:
CursorWindow: Window is full: requested allocation 2202504 bytes, free space 2076560 bytes, window size 2097152 bytes在第一种情况下,请求分配比窗口大小小得多。我希望类似的消息会重复发出,窗口大小相同,所请求的分配大小也不同。每次打印时,都会从较大的窗口释放内存,并进行新的分配。这是正常和健康的操作。
在第二种情况下,请求的分配大小超过了整个窗口大小。这是一个实际的问题,需要以更流畅的方式存储和读取数据。
区别是“长度”(行总数)与“宽度”(最大一行的内存成本)。前者(@tirrel的问题)不是一个问题,但后者(@vovahost的问题)是一个问题。
发布于 2017-10-08 23:45:00
我也有这个问题。在我的例子中,我在数据库中保存了一个2.2MB的映像。当使用Cursor.getBlob()从数据库加载数据时,我会在日志中看到以下消息:
CursorWindow: Window is full: requested allocation 2202504 bytes, free space 2076560 bytes, window size 2097152 bytes如果我试图检索连续行的任何数据(字符串、数字等),在获得此消息之后,它将作为null返回,不会出现任何错误。解决方案是删除2.2MB的blob。我不知道是否有可能从Android的数据库中加载更大的小块。
https://stackoverflow.com/questions/20094421
复制相似问题