我想创建一个工具栏,当悬停时它会旋转和展开。但内存泄漏非常严重,可能会消耗任意RAM,初始内存使用量约为20MB,1000次动画后达到300mb。我只使用基本组件,如ListView,Rectangle和MouseArea。这是完整的源代码。我是qml的新手。任何建议将不胜感激,谢谢。
//MyListView.qml
//The ListView will expand when activated.
ListView{
id:root
orientation: ListView.Horizontal
property alias list: listModel
width: calcWidth()
signal optionSelected(string option)
function enableItems(big){
for(var i in root.contentItem.children){
var child = root.contentItem.children[i]
if(child.objectName!=="delegate") continue
if(big){ child.state="big" }
else child.state=""
}
}
function calcWidth(){
var w = 0
for(var i in root.contentItem.children) {
var child = root.contentItem.children[i]
if(child.objectName==="delegate"){
w+=child.width
}
}
return w
}
model: ListModel{
id:listModel
}
delegate: Rectangle{
id: rect
objectName: "delegate"
height: parent.height
width: 0
color:"transparent"
border.color:"grey"; border.width:1; radius: 5
rotation: width/root.height * 360
states:State{
name: "big"
PropertyChanges{
target: rect; width: root.height
}
}
transitions: Transition {
from: "*"
to: "big"
reversible: true
NumberAnimation{
properties: "width";easing.type: Easing.OutQuad; duration: 400
}
}
Image{
anchors.fill: parent
source: imgSrc
}
MouseArea{
anchors.fill: parent
hoverEnabled: true
onEntered: enableItems(true)
onExited: enableItems(false)
onClicked: root.optionSelected(option)
}
}
}
//MyRow.qml
Row{
id:root
width: mainImg.width + listView.width
property alias list: listView.list
property alias mainImg: mainImg.source
signal optionSelected(string option)
Image{
id: mainImg; height: parent.height; width: parent.height
MouseArea{
anchors.fill: parent
hoverEnabled: true
onEntered: listView.enableItems(true)
onExited: listView.enableItems(false)
}
}
MyListView{
id: listView
height: root.height
onOptionSelected: root.optionSelected(option)
}
//test memory usage
Timer{
id: timer
running: true; interval: 400; repeat: true
property real times:0
property bool big :false
onTriggered: {
times ++
big = !big
listView.enableItems(big)
console.log(big+""+times)
if(times>500){
timer.running = false
gc()
}
}
}
}
//main.qml
Rectangle {
width: 360
height: 360
MyRow{
height: 128
mainImg: "qrc:/4.png"
onOptionSelected: console.log(option)
Component.onCompleted: {
list.append({imgSrc:"qrc:/1.png",option:"111"})
list.append({imgSrc:"qrc:/2.png",option:"222"})
list.append({imgSrc:"qrc:/3.png",option:"333"})
}
}
}
Edit1:我使用的是Qt 5.5.0 + Linux Mint 17.1 + KDE。切换到Qt 5.4.2 + Windows 10后,一切正常。
答案 0 :(得分:1)
我不相信你确实已经建立了内存泄漏。 QML引擎将缓存,看起来内存使用量上升20-30 mb是一件很常见的事情。
但内存泄漏严重
没有任何具体的数字,人们只能猜出你的意思。内存使用量是否超过30 MB并继续上升?它达到了100吗?还是更多?
请记住JS是垃圾收集的,根据我自己的经验收集远非逻辑,至少在QML中。有时我会在应用程序生命周期中一直使用非引用对象,有时我会在QML因某种原因决定删除它们时得到仍在使用的对象,结果是段错误和崩溃。
顺便说一句,您可以使用gc()
强制进行垃圾回收,看看是否有任何好处。
正如在this similar post中已经确定的那样,“正常”的行为是记忆会上升到某一点然后稳定下来,我怀疑这种情况也会发生在你的情况下。您应该进一步调查并发布具体数字,并在必要时发布错误报告。
编辑:我在Qt 5.42上测试了你的示例代码,内存使用量很快就达到了47.068 MB,并且在500个动画之后它仍然存在,根据任务管理器还没有向上移动一个kb,它实际上已经下降了如果动画停止则很少,如果恢复则返回47.068 MB。使用Qt 5.5,它稳定在51.672 MB
如果您运行的字面上相同的代码,您的Qt版本可能有一个错误。