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?

- 1,021
- 1
- 19
- 36
-
Should be, with an `asyncronous` Loader. But this property fails me somehow. While the `UI` does not freeze as promised (`BusyIndicator` running) it is still completely unresponsive. – derM - not here for BOT dreams Apr 12 '17 at 14:21
-
I have `asynchronous` set, but the problem is it destroys objects in Loader while they are not finished loading, which causes warnings and errors. – Rinat Veliakhmedov Apr 12 '17 at 14:44
-
What about setting `active` to false or setting `source`/`sourceComponent` to null? – folibis Apr 12 '17 at 14:54
-
I don't know what went wrong earlier, but uppon writing it once again, it works... – derM - not here for BOT dreams Apr 12 '17 at 15:20
-
@folibis then it seems to never delete any objects and eventually runs out of memory. – Rinat Veliakhmedov Apr 13 '17 at 13:49
2 Answers
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
.
Bugs
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).

- 10,244
- 7
- 28
- 56
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))
}
}
}
}

- 235,170
- 19
- 170
- 241

- 13,081
- 4
- 49
- 89
-
If you keep clicking button very fast, it never frees memory allocated for previous objects and eventually causes bad_alloc. – Rinat Veliakhmedov Apr 13 '17 at 13:47
-
How often did you click with my `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... – derM - not here for BOT dreams Apr 13 '17 at 14:33
-
I set the timer to 200, but increased the number of rows and columns to 200. It grows memory very fast and crashes. – Rinat Veliakhmedov Apr 13 '17 at 14:38
-
For 200x200, I do not see any memory increase (constant ~200MB). For smaller size (50x50), I do so see an increase, but this can be avoided by calling `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. – m7913d Apr 14 '17 at 16:03
-
@m7913d : Interesting that this happens to you. At the beginning I had exactly the same problem (well, actually the GUI-thread it self seemd to work, so the BusyIndicato if I remember it right, kept spinning, but the `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 – derM - not here for BOT dreams Apr 14 '17 at 18:02
-
The above results were for using `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. – m7913d Apr 14 '17 at 18:55
-
@m7913d I'm on Windows, calling `gc` does basically nothing (I use `QQmlApplicationEngine`). – Rinat Veliakhmedov Apr 14 '17 at 23:40
-
This definitely seems to be a Qt bug. Can I use your example to fill in a bug report? – m7913d Apr 15 '17 at 08:17
-
I submitted a [bugreport](https://bugreports.qt.io/browse/QTBUG-60188) including a possible solution. – m7913d Apr 15 '17 at 10:52
-
@m7913d I'll write a support request when I get to my work laptop, maybe it'll get resolved faster. – Rinat Veliakhmedov Apr 15 '17 at 12:27
-
1Check whether calling `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. – dtech Apr 17 '17 at 20:01
-