连续缓存示例

连续缓存示例展示了如何使用 QContiguousCache 来管理非常大的模型的内存使用。在某些环境下内存是有限的,即使内存不是有限的,用户也不喜欢应用使用过多的内存。使用 QContiguousCache 来管理列表,而不是将整个列表加载到内存中,允许应用限制其使用的内存量,无论访问的数据集有多大。

使用 QContiguousCache 最简单的方法是在请求项目时进行缓存。当一个视图请求第N行的项目时,它也可能请求与N行接近的行。

QVariant RandomListModel::data(const QModelIndex &index, int role) const
{
    if (role != Qt::DisplayRole)
        return QVariant();

    int row = 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));
    }

    return m_rows.at(row);
}

void RandomListModel::cacheRows(int from, int to) const
{
    for (int i = 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

版权所有© 2024 Qt公司有限公司。此处包含的文档贡献的版权属于各自所有者。本提供的文档受《由自由软件基金会发布的GNU自由文档许可证版本1.3》的条款许可http://www.gnu.org/licenses/fdl.html。Qt及其相关标志是芬兰以及全球其他国家的Qt公司有限责任公司的商标。商标。所有其他商标均为各自所有者的财产。