复制项目时中继器模型非常慢

问题描述 投票:0回答:1

我们的项目面临性能问题。我们正在使用 Qt/QML 和 C++ 后端,并且正在开发网格按钮。如果我们更改或更新数据模型,中继器部分需要更多延迟来更新所有按钮,因此 UI 非常慢。根据按钮数量,延迟会增加,如果更新 64 个按钮,则意味着加载需要 6 秒。

当我们尝试更新数据或将对象数组复制到Repeater的模型容器(数据模型)中时,复制所有项目会消耗更多时间。例如,30 个对象耗时 2 秒。如果对象数量增加,那么消耗的时间也会成比例增加。

根据控制台调试打印,执行此行后

console.log("GRID update data model")
,执行下一条命令需要2秒。

如何避免中继器出现这种延迟?

  • 目标处理器名称:IMX537
  • Qt版本:Qt 5.15.2(GCC 9.3.0,64位)

注意:此延迟问题仅发生在目标设备中。在本地编译中没有看到这个延迟。

代码:

 function handleModelChanged() {
        delegateModel.model = areaViewModel;
        const newUiType = areaViewModel.uiType
        if (newUiType !== uiType || !modelDataIsEqual(delegateModel, dataModel) ) {
            var buttons = [] 

            for (var row = 0; row < delegateModel.model.rowCount(); row++) {
                var item = delegateModel.items.get(row).model;
                var button = dataModelItemToButton(item);
                
                buttons.push(button);
            }
            console.log("GRID clear data model")
            dataModel = []
            console.log("GRID change uiType " + uiType + " -> " + newUiType)
            uiType = newUiType
            console.log("GRID update data model")
            dataModel = buttons;
            console.log("GRID buttons changed uiType=" + uiType + " cls=" + areaViewModel.callClass);
             
        }  
    }
    Repeater 
    {
        id: areaRepeater
        model: dataModel

        delegate: {
                gridButton;
            }
        onItemAdded: {              
            if (index == areaRepeater.count - 1) {
                console.log("GRID repeater added " + areaRepeater.count + " buttons")
                updateItems()
                }
            }
        }
    }


function modelDataIsEqual(modelData, data) {
        if (!modelData || !data || modelData.model.rowCount() !== data.length)
            return false;
        for (var i = 0; i < modelData.model.rowCount(); ++i) {
            const item = modelData.items.get(i).model;
            const button = data[i];
            if (button.dataAreaShortName !== item.dataAreaShortName ||
                    button.dataAreaName !== item.dataAreaName ||
                    button.dataIsExitArea !== item.dataIsExitArea ||
                    button.dataAreaGridCols !== item.dataAreaGridCols ||
                    button.dataIsGroupedButton !== item.dataIsGroupedButton ||
                    button.dataAreaLocked !== item.dataAreaLocked ||
                    button.dataAreaIcon !== item.dataAreaIcon ||
                    button.dataIsDopArea !== item.dataIsDopArea ||
                    button.dataIsSideGroup !== item.dataIsSideGroup ||
                    dlaButtonStyle !== areaModel.combineBtnStyle ||
                    oddEvenBtnAppearance !== areaModel.getLockedButtonAppearance() ||
                    button.dataButtonAppearance !== item.dataButtonAppearance ||
                    button.dataCrowdedArea !== item.dataCrowdedArea ||
                    button.dataOverCrowdedArea !== item.dataOverCrowdedArea ||
                    button.dataPeopleIconArea  !== item.dataPeopleIconArea ||
                    button.dataSideStateIconArea !== item.dataSideStateIconArea)
            {
                return false;
            }
        }
        return true;
    }

正如我上面提到的,按钮数量增多意味着延迟也会增加。就像将一个按钮输入模型需要 100 毫秒。在某处提到在 Repeater 中使用 ListModel 来加载数据项。但我也尝试过,似乎也发生了同样的延迟。

qt qml repeater datamodel listmodel
1个回答
0
投票

当处理大量按钮时,即使在Repeater中使用ListModel,也可能有其他因素导致速度变慢。

代码中的性能问题可能是由于 modelDataIsEqual 函数造成的,该函数似乎在循环内进行了多次比较。比较循环内对象的每个属性可能代价高昂,特别是当对象很复杂或具有嵌套属性时。

function modelDataIsEqual(modelData, data) {
if (!modelData || !data || modelData.model.rowCount() !== data.length) {
    return false;
}

const modelRowCount = modelData.model.rowCount();

for (let i = 0; i < modelRowCount; ++i) {
    const item = modelData.items.get(i).model;
    const button = data[i];

    const isEqual = (
        button.dataAreaShortName === item.dataAreaShortName &&
        button.dataAreaName === item.dataAreaName &&
        button.dataIsExitArea === item.dataIsExitArea &&
        button.dataAreaGridCols === item.dataAreaGridCols &&
        button.dataIsGroupedButton === item.dataIsGroupedButton &&
        button.dataAreaLocked === item.dataAreaLocked &&
        button.dataAreaIcon === item.dataAreaIcon &&
        button.dataIsDopArea === item.dataIsDopArea &&
        button.dataIsSideGroup === item.dataIsSideGroup &&
        dlaButtonStyle === areaModel.combineBtnStyle &&
        oddEvenBtnAppearance === areaModel.getLockedButtonAppearance() &&
        button.dataButtonAppearance === item.dataButtonAppearance &&
        button.dataCrowdedArea === item.dataCrowdedArea &&
        button.dataOverCrowdedArea === item.dataOverCrowdedArea &&
        button.dataPeopleIconArea === item.dataPeopleIconArea &&
        button.dataSideStateIconArea === item.dataSideStateIconArea
    );

    if (!isEqual) {
        return false;
    }
}

return true;}
© www.soinside.com 2019 - 2024. All rights reserved.