首页 > 解决方案 > ListView如何实现更好的缓存控制?

问题描述

我尝试使用 cacheBuffer,但是当我想完全禁用缓存时,它只会帮助我增加缓存委托的数量。

现在使用零缓存缓冲区,我的示例(在所有 ListView 上仅拉伸一项)的行为如下:

这种行为正常吗?我可以以某种方式改变它吗?

你可以自己试试:

import QtQuick 2.11
import QtQuick.Controls 2.4
import QtQuick.Window 2.11

import Qt.labs.calendar 1.0

Window {
    id: root

    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    ListView {
        id: listView

        anchors.fill: parent
        snapMode: ListView.SnapOneItem
        cacheBuffer: 0

        model: 10

        delegate: Rectangle {
            width: parent.width
            height: root.height
            // height: listView.height
            border.color: "black"

            Text {
                anchors.centerIn: parent

                text: modelData
            }

            Component.onCompleted: {
                console.log("Delegate completed")
            }

            Component.onDestruction: {
                console.log("Delegate destruction")
            }
        }
    }
}

标签: qtqml

解决方案


代替

 delegate: MyVeryComplexDelegate {
 }

经过

delegate: Loader {
    width: expectedDelegateWidth
    height: expectedDelegateHeight // Otherwise you might create all...
    sourceComponent: MyVeryComplexDelegate {
    }
    active: someCriteriaYouFeelGoodAbout()
}

现在您的缓存中将只有 simple Loaders,您可以决定缓存中的哪些是活动的。


可能更好:根据需要MyVeryComplexDelegate加载部分内容,并且仅在您确实需要全部复杂性时才ListView将最复杂的部分隐藏在激活的 a 后面。Loader


据我所知,关于你的奇怪发现:

关于 和 之间的区别root.heightlistView.height解释是一个涉及许多问题的问题:

虽然root.height引用了height您已明确设置的窗口属性,但listView.height由 确定anchors.fill: parent,这导致将高度设置为root.contentItem.height- 并且最初为0。因此,代表最初的高度0均为 ,它们都将适合视图,因此必须创建,即使您尽可能地延迟加载。稍后它们将与 一起调整大小,root.contentItem并且一些将再次被销毁。

你可以看到,当监控你的代表和你的高度变化时ListView

接下来的事情是,即使委托真的ListView从头开始填充,第二个委托也会被实例化。原因是ListView, 何时创建新委托所使用的条件。为此,高度的总和 - 第一个的位移必须大于ListView当它等于高度时,这不满足。

将您的委托增加height几分之一像素,您就很好了。

height: root.height + 0.0001

推荐阅读