Tir*_*rel 31 database android cursor android-listview
我已经创建了一个ListView,它由查询返回的数据填充.
它有效,但在LogCat中我收到了消息:
Cursor Window: Window is full: requested allocation 444 bytes, free space 363 bytes, window size 2097152 bytes
Run Code Online (Sandbox Code Playgroud)
它使用几分钟来加载/可视化ListView.
我的查询返回大约3700行String/Int/Double,每行包含30列; 没有图像或特定数据类型
这条消息究竟意味着什么,我该如何避免呢?
您可以通过更改此光标窗口来提高性能吗?
我也遇到这个问题。就我而言,我在数据库中保存了 2.2 MB 的图像。使用从数据库加载数据时,Cursor.getBlob()我会在日志中看到以下消息:
CursorWindow: Window is full: requested allocation 2202504 bytes, free space 2076560 bytes, window size 2097152 bytes
Run Code Online (Sandbox Code Playgroud)
在我收到此消息后,如果我尝试检索连续行的任何数据(字符串、数字等),它将返回为空,没有任何错误。解决方案是删除 2.2 MB 的 blob。我不知道是否可以从 Android 数据库中加载更大的 blob。
精简版:
经过一番调查后,看来此消息是正常操作的一部分,并不是引起关注的原因.它记录在"警告"级别,但我认为这只是过度的操作.
更长的版本:
这是(明确标记为)"窗口"光标,这意味着旧记录将在获得新记录时被丢弃.在最简单的形式中,这样的"窗口"实现可以包含总共多达N行,可能具有一些预读.然而,在该实现中,窗口大小由总大小来定义.保留在内存中的行数取决于整个窗口中适合的行数,并且在运行时会有所不同(这可能更多地被视为"缓冲"光标而不是"窗口"光标).
作为具有(soft - ?)上限大小的缓冲实现,只有当缓冲区太满而无法容纳下一行时,才会丢弃最早的行.在这种情况下,丢弃一个或多个较旧的行.这"根据需要继续分配行,直到我们不再有更多的空间,此时我们释放缓冲区中最旧的记录并再次尝试"过程似乎是完全正常和预期的,作为正常部分保持内存空间受限的过程
我在这里阅读源代码时得出了这个结论,并结合了一些推论: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
Run Code Online (Sandbox Code Playgroud)
这是@vovahost得到的消息:
CursorWindow: Window is full: requested allocation 2202504 bytes, free space 2076560 bytes, window size 2097152 bytes
Run Code Online (Sandbox Code Playgroud)
在第一种情况下,请求的分配比窗口大小小得多.我希望重复发出类似的消息,具有相同的窗口大小和不同的请求分配大小.每次打印时,都会从较大的窗口中释放内存,并进行新的分配.这是正常和健康的运作.
在第二种情况下,请求的分配大小超过了整个窗口大小.这是一个实际问题,需要以更流畅的方式存储和读取数据.
差异是"长度"(总行数)与"宽度"(最大单行的内存成本).前者(@ tirrel的问题)不是问题,但后者(@ vovahost的问题)是.