Do not fear! This is not production code. It is just to learn new things about QML! I do not seek 'you shall not do something like this - do it like that.' I am more interested in the internals of QML
Consider the following QML-Code
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)
}
}
}
}
It illustrates to some extent the MemoryManagement of QML when using dynamic ObjectCreation (JS).
I have a ListView
, that creates a few delegates, and lets me browse through them, creating new one on demand.
The trick is: When ever a new delegate is created, it uses the JavaScript
Dynamic Object Creation to create two instances of an text-object.
One of them is parented to the delegate, the other one is parented to null
and it's life is therefore determined by the JS-Engine. It should be garbage collected, once there is no pointer left, pointing towards it.
For the start, I will put both of them in a frame
(Item
), to display (setting a visual parent). As the delegate, those frames are destroyed.
This will - as expected - destroy the dynamically created Object that has the delegate as parent, as well. The other one is (should be) left for the Garbage Collector to do his work.
And this is where it fails - sometimes the application crashes before the GC kicks in, sometimes it crashes, while the GC is trying to do its work.
Though it is not reccommended by the documentation, it does help, to call the GC manualy (activate the line commented out in Component.onCompleted
).
So it seems to me, the GC overestimates it's abilities, and decides to kick in, when it is already to late.
What might be the reason for this? Is there a way to tell the GC to be mor proactive?
Again: I do not intend to use the Dynamic Object Creation with
.createObject(null)
in my code. It is pure curiosity.