I have a Loader
object that loads some very heavy components. Some event arrives in the middle of the load that requires loading to stop and go back to empty the Loader
. Is it possible?
Abort object creation
As documented by Qt, three methods exists to unload/abort an object instantiation:
- Set
Loader.active
tofalse
- Set
Loader.source
to an empty string - Set
Loader.sourceComponent
toundefined
Asynchronous behaviour
To be able to change these properties during loading, Loader.asynchronous
should be true
, otherwise the GUI thread is busy with loading the object. You also need to QQmlIncubationController
for your QQmlEngine
to control the idle time used for object incubation. Without such a controller Loader.asynchronous
does not have any effect. Note that QQmlApplicationEngine
automatically installs a default controller if the scene contains a QQuickWindow
.
Bug: memory leak
Up to the last tested Qt version (Qt 5.8.0, 5.9.0 beta), a severe memory leaks exist when aborting an unfinished object incubation (at least in certain cases, including the example in the answer of derM) resulting in a fast memory usage increase for large components. A bug report is created including a proposed solution.
According to the bug report, this should be fixed in Qt version 5.15 (not tested).
I don't know what your issu is, with those objects that are destroyed before the loader finishs, but maybe the issue is there? If not, this should work: If it does not help, please add some code to your question, that reproduces your problem.
main.qml
import QtQuick 2.7
import QtQuick.Controls 2.0
ApplicationWindow {
id: root
visible: true
width: 400; height: 450
Button {
text: (complexLoader.active ? 'Loading' : 'Unloading')
onClicked: complexLoader.active = !complexLoader.active
}
Loader {
id: complexLoader
y: 50
width: 400
height: 400
source: 'ComplexComponent.qml'
asynchronous: true
active: false
// visible: status === 1
}
BusyIndicator {
anchors.fill: complexLoader
running: complexLoader.status === 2
visible: running
}
}
ComplexComponent.qml
import QtQuick 2.0
Rectangle {
id: root
width: 400
height: 400
Grid {
id: grid
anchors.fill: parent
rows: 50
columns: 50
Repeater {
model: parent.rows * parent.columns
delegate: Rectangle {
width: root.width / grid.columns
height: root.height / grid.rows
color: Qt.rgba(Math.random(index),
Math.random(index),
Math.random(index),
Math.random(index))
}
}
}
}
ComplexComponent
? :D I opted for a timer clicking every 200 or 500 ms, and did that for multiple minutes. But yes, the memory increases over time... –
Combs gc
(i.e. garbage collection) manually after unloading. Except for the first time, button.clicked()
takes a lot of time (up to 6s for 200x200), the GUI freezes, and the file is not loaded asynchronously (Loader.Status
never becomes Loader.Loading
). Tested on Qt 5.8, Ubuntu 16.04. –
Fremont Button
was indicated as down
the whole time, and it was unloaded only after the loading was completed. Then I wanted to post this as an example that does not work when it suddenly worked. Tried it on several machines (Linux and Windows) by now, and it works for me :D –
Combs QQuickWidget
. I switched to QQmlApplicationEngine
(which creates a QQmlIncubationController
automatically if the scene contains a QQuickWindow
) and now asynchronous
and aborting works, but memory leaks seem to occur. gc
doesn't work anymore to clean up memory. –
Fremont gc
does basically nothing (I use QQmlApplicationEngine
). –
Alina gc()
3-4 times in a row has an effect on memory usage. One rarely suffices, but 3-4 seem to squeeze as much garbage out as possible. –
Laoighis © 2022 - 2024 — McMap. All rights reserved.
asyncronous
Loader. But this property fails me somehow. While theUI
does not freeze as promised (BusyIndicator
running) it is still completely unresponsive. – Combsasynchronous
set, but the problem is it destroys objects in Loader while they are not finished loading, which causes warnings and errors. – Alinaactive
to false or settingsource
/sourceComponent
to null? – Insociable