连续缓存示例

“连续缓存”示例演示了如何使用QContiguousCache 来管理超大规模模型的内存使用情况。 在某些环境中,内存资源有限;即使内存充足,用户也不希望应用程序占用过多内存。通过使用QContiguousCache 来管理列表(而非将整个列表加载到内存中),应用程序便能够限制其内存占用量,无论所访问的数据集规模如何。

使用QContiguousCache 的最简单方法是在请求项目时进行缓存。当视图请求第N行的项目时,通常也会请求与N行相邻的项目。

QVariant RandomListModel::data(constQModelIndex&index, introle)const
{
    if(role!=Qt::DisplayRole)
        returnQVariant();

    introw=index.row();

    if(row>m_rows.lastIndex()) {
        if(row-m_rows.lastIndex()>lookAhead)
            cacheRows(row-halfLookAhead, qMin(m_count,row+halfLookAhead));
        else while(row>m_rows.lastIndex())
                m_rows.append(fetchRow(m_rows.lastIndex()+ 1));
    }else if(row<m_rows.firstIndex()) {
        if(m_rows.firstIndex()-row>lookAhead)
            cacheRows(qMax(0, row - halfLookAhead), row + halfLookAhead);
       else while(row<m_rows.firstIndex())
                m_rows.prepend(fetchRow(m_rows.firstIndex()- 1));
    }

    returnm_rows.at(row);
}

voidRandomListModel::cacheRows(intfrom, intto)const
{
    for(inti=from; i<=to;++i)
        m_rows.insert(i,fetchRow(i));
}

获取行后,该类会判断该行是否位于连续缓存当前范围之内。若直接采用以下代码,效果同样有效。

while (row > m_rows.lastIndex())
    m_rows.append(fetchWord(m_rows.lastIndex()+1);
while (row < m_rows.firstIndex())
    m_rows.prepend(fetchWord(m_rows.firstIndex()-1);

然而,如果直接使用滚动条,列表往往会跨行跳转,导致上述代码会将旧行与新行之间的每一行都加载进来。

通过使用QContiguousCache::lastIndex() 和QContiguousCache::firstIndex(),该示例可以确定缓存当前缓存了列表的哪一部分。这些值并不代表缓存自身内存中的索引,而是一个由缓存表示的虚拟无限数组。

通过使用QContiguousCache::append() 和QContiguousCache::prepend(),该代码可确保当请求的行未偏离当前缓存范围太远时,仍可能显示在屏幕上的项目不会丢失。QContiguousCache::insert() 可能会从缓存中移除多个项目,因为QContiguousCache 不允许存在间隙。 如果您的缓存需要在行与行之间存在较大间隔的情况下快速来回跳转,请考虑改用QCache 。

就这样。这是一个非常合理的缓存方案,仅使用极少的内存即可处理非常大的列表。在此示例中,将单词放入缓存的访问器会生成随机信息,而非固定信息。这使您在运行示例时能够观察到缓存范围如何针对局部行数进行维护。

QString RandomListModel::fetchRow(int position) const
{
    return QString::number(QRandomGenerator::global()->bounded(++position));
}

此外,还值得考虑在应用程序的绘制例程之外将项目预先加载到缓存中。这可以通过单独的线程实现,也可以使用QTimer ,在行被请求出当前缓存范围之前,逐步扩展缓存范围。

示例项目 @ code.qt.io

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.