不要害怕!这不是生产代码。它只是学习QML的新东西!我不寻求你不会做这样的事情 - 这样做。'我对QML的内部更感兴趣
考虑以下QML代码
import QtQuick 2.4
import QtQuick.Window 2.0
Window {
id: root
width: 800
height: 600
visible: true
GridView {
width: 800
height: 200
model: 4000
flow: GridView.FlowTopToBottom
delegate: Rectangle {
id: myDelegate
width: 100
height: 100
border.width: 1
Column {
anchors.fill: parent
Text {
text: index
height: 20
width: parent.width
}
Item {
id: frame0
height: 20
width: parent.width
}
Item {
id: frame1
height: 20
width: parent.width
}
}
Component.onCompleted: {
// if (index % 100 === 0) gc()
frame0.children = [myComp.createObject(myDelegate)]
frame1.children = [myComp.createObject(null)]
frame0.children[0].text = 'QML ' + index
frame1.children[0].text = 'JS ' + index
}
}
Component {
id: myComp
Text {
anchors.centerIn: parent
Component.onDestruction: console.log('Destroy ' + text)
}
}
}
}
在使用动态ObjectCreation(JS)时,它在某种程度上说明了QML的MemoryManagement。
我有一个ListView
,可以创建一些代表,让我浏览它们,按需创建新的代理。
技巧是:当创建新委托时,它使用JavaScript
动态对象创建来创建文本对象的两个实例。
其中一个是代表的父级,另一个是null
的父级,因此它的生命由JS-Engine决定。它应该是垃圾收集,一旦没有指针,指向它。
首先,我会将它们放在frame
(Item
)中,以显示(设置可视父级)。作为代表,这些框架被销毁。
这将 - 正如预期的那样 - 破坏动态创建的对象,该对象也将委托作为父对象。另一个(应该)留给垃圾收集器来完成他的工作。
这就是它失败的地方 - 有时候应用程序会在GC启动之前崩溃,有时会崩溃,而GC正在尝试完成它的工作。
虽然文档没有推荐,但确实有助于手动调用GC(激活Component.onCompleted
中注释掉的行。)
所以在我看来,GC高估了它的能力,并决定在已经迟到的时候开始。
这可能是什么原因?有没有办法告诉GC是否主动?
再次:我不打算在我的代码中使用
.createObject(null)
创建动态对象。这是纯粹的好奇心。
答案 0 :(得分:2)
这可能是什么原因?有没有办法告诉GC mor主动?
原因是buggy qtquick object lifetime实施。在这一点上,它看起来不是一个JS的东西,而是一个qtquick的东西。它显然是doesn't abide to its own alleged rules - 例如,它会在仍在使用时删除具有父项的对象,从而导致硬崩溃。您不能指望引用计数也能正常工作。在许多采用动态的场景中可能会发生此行为,通常不会在琐碎和静态场景中显示。
如链接问题中所述,解决方案是使用手动对象生存期管理。使用一组新函数来创建和删除对象。
QQmlEngine::setObjectOwnership(ojb, QQmlEngine::CppOwnership);
,这基本上告诉qtquick"不要打扰尝试",幸运的是至少这可以按原样使用obj->deleteLater();
对我来说,这就是诀窍,我不会因为没有明显的原因而崩溃。使用自定义生命周期管理并远离库存功能。它给你保证,只要你需要它就会保持对象 ,但它也不会超出你想要的那个点,这是另一个问题,尽管不是那么严重。当然,这消除了使用JS的便利因素,因为你必须放弃自动生命周期管理,并且使用自己的代码更加勤奋和明确,但是你无法做很多事情。虽然这个漏洞几乎在一年前被报道并被认为是 critical ,但并没有对它做过任何一件事。因此,我认为,作为严重,因为它可能在其严重性中,在找到原因并修复它时更像是最低优先级。