Detect if delegate item inside ListView has been destroyed
-
Hi, I have a special problem, kinda :D
I have a ListView with item delegates like usual, but my ListView model contains only partial data and for every delegate item extra data is being dynamically loaded when the delegate is completed.
short example:
@
ListView {
...
delegate: Item {
...
Text { id: textItem }
Component.onCompleted: webservice.loadDataAsync(function(data) {
textItem.text = data.text // this may crash the app
})
}
}
@so I have a web service in C++ and call the slot loadDataAsync with a JavaScript closure as a callback, that works fine the problem is just if you scroll around in the ListView and the callback gets called after the delegate has been destroyed by the QML/JS engine the app will crash.
That might happen if you scroll fast or the web service is slow obviously, so if the callback is called after the delegate has been destroyed the items in the delegate doesn't exist anymore and the QMl engine crashed because it can't fine the item id...so my question is can I somehow check if the delegate has been destroyed in the callback function or does anyone have a better solution maybe? thanks.
from C++ I check if the callback is valid and callable, but I don't think I can access the delegate or anything more from there, the callback is simply of type QJSValue.
btw I like that you can do crazy JavaScript/C++ interaction like this lol
-
Just a suggestion, but can testing for undefined (or maybe null) work?
@Component.onCompleted: webservice.loadDataAsync(function(data) {
if (textItem !== undefined)
textItem.text = data.text // this may crash the app
})@ -
hey thanks for the answer, but that doesn't work because the id lookup in the QML engine crashes I belive. maybe the stacktrace of the crash helps:
bq.
0 QV4::__qmljs_get_id_object qv4runtime.cpp 1236 0x8262dc9
1 QQmlJS::Moth::VME::run qv4vme_moth.cpp 652 0x82b2996
2 QQmlJS::Moth::VME::exec qv4vme_moth.cpp 707 0x82b2d45
3 QV4::Function::code qv4function_p.h 89 0x84271c2
4 QV4::SimpleScriptFunction::call qv4functionobject.cpp 598 0x8280441
5 QV4::Managed::call qv4managed_p.h 343 0x8426f7c
6 QV4::__qmljs_call_value qv4runtime.cpp 928 0x8261c23
7 QQmlJS::Moth::VME::run qv4vme_moth.cpp 347 0x82ade76
8 QQmlJS::Moth::VME::exec qv4vme_moth.cpp 707 0x82b2d45
9 QV4::Function::code qv4function_p.h 89 0x84271c2
10 QV4::SimpleScriptFunction::call qv4functionobject.cpp 598 0x8280441
11 QV4::FunctionObject::call qv4functionobject_p.h 130 0x841f6dc
12 QJSValue::call qjsvalue.cpp 521 0x8253a0b
...the crash happens in QV4::__qmljs_get_id_object, also when I print the ID to the console with
@
console.log(textItem)
@
I get a pointer to a QQuickText and never a null pointer :/
@
QQuickText(0x2644ef98)
@
I guess the QMl engine never sets the pointer to 0 and just deletes the item?anyway for now I have a workaround to set a flag in the "Component.onDestruction" slot so that the callback won't be called, but there are rare cases where it still crashes, but only if you scroll around like crazy. so it works for now but I think there should be a better way of detecting this case.
-
I was just playing around with "ListView.delayRemove: true", so if I just set that in the ListView delegate the items will never be destroyed, since I have only 15 items in the list I think that will be an option if that is "good practice" and I can just leave the ListView.delayRemove set to true forever?
-
Sounds like there may be a bug in the Qt Qml engine wrt handling the function expression here. Please file a bug report for it if you can.
If your list only has 15 items and you don't need dynamic delegates, a Column with a Repeater inside a Flickable is maybe all you need.
-
I don't know if this a bug, but it is a little weird.
I use a ListView at that place because a Column or Row will generate all delegates directly or won't it? The ListView will dynamically load more item when scrolled further, so if the user never scrolls to the end the delegates don't need to be generated and the data not loaded..