Setting Loader.active to false doesn't release item immediately

只谈情不闲聊 提交于 2019-11-29 18:37:53

It's not really a bug, but more like a technical limitation. A slot must not delete the sender of the connected signal. It must use deleteLater() to avoid that the execution returns to a deleted object. Essentially for the same reason, Loader cannot immediately delete the loaded item, because the active property might be bound to something that is controlled from within the loaded hierarchy of items.

I came across this yesterday. I need two Loaders which share the same property. In C++ class, I update the two Loader's active property one by one, which will also lead to that problem. My solution for this is using a Binding and do some setting like this:

Binding {
        target: contentItemAlias
        property: 'currentIndex'
        value: if (header.status == Loader.Ready) 
        header.item.currentIndex //ensure the current status is not null
        when: content.status === Loader.Ready // the content is ready
    }

Actually maybe this will not help you, but this is the solution in my code. I hope you will see it and have a try at binding. Wish you success. here is the link to my project: https://github.com/begoat/qmlLive

Even though it wasn't new to me that QML objects' destroy() is a deleteLater() and the latter doesn't destroy the object until the next event loop cycle, I expected such objects to stop processing events after that point.

It seems the object keeps on living for a while, and its bindings keep on being evaluated, failing to resolve because unlike the object destruction, the property setting happens instantaneously.

And since it wasn't an option to ever have null in the item, I managed to work-around the issue by having a global dummy data object and using a conditional binding:

active: object.data // for loader

data: loader.active ? object.data : Globals.dummydata // in item

This seems to work, providing dummy data to the object in its final moments.

You can also use Connections to connect to the Loader's onActiveChanged-event and break the binding there:

Loader {
    id: ld
    active: false
    sourceComponent: Text {
        text: object.subObject.i
        font.pointSize: 20

        Connections {
            target: ld
            onActiveChanged: {
                if (active) return
                text = text // This will overwrite the binding by the last value of the property itself.
            }
        }
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!