Не бойтесь! Это не производственный код. Это просто узнать о QML! Я не ищу «вы не будете делать что-то подобное - сделайте это так». Я больше заинтересован в внутренностей QMLGC аварии QML-приложение
Рассмотрим следующий QML-код
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)
}
}
}
}
Это иллюстрирует в некоторой степени MemoryManagement из QML при использовании динамического ObjectCreation (JS). У меня есть ListView
, который создает несколько делегатов и позволяет мне просматривать их, создавая новые по требованию.
Уловка: когда создается новый делегат, он использует создание динамического объекта JavaScript
для создания двух экземпляров текстового объекта.
Один из них является родительским для делегата, а другой - от null
, и поэтому его жизнь определяется JS-Engine. Это должен быть сбор мусора, когда нет указателя слева, указывая на него.
Для начала отправьте оба из них в frame
(Item
), чтобы отобразить (установить визуальный родитель). Как делегат, эти рамки уничтожаются. Это, как и ожидалось, уничтожит динамически созданный объект, который также имеет делегат как родительский. Другой (должен быть) оставлен для Мусороуборочного завода для выполнения его работы.
И здесь это не удается - иногда приложение выходит из строя, прежде чем GC запускается, иногда он падает, в то время как GC пытается выполнить свою работу.
Хотя это не рекомендуется документацией, оно действительно помогает вызвать GC manualy (активировать строку, прокомментированную в Component.onCompleted
).
Итак, мне кажется, GC переоценивает свои способности и решает нанести удар, когда уже будет поздно.
Что может быть причиной этого? Есть ли способ сказать GC быть mor proactive?
Опять: Я не намерен использовать динамическое создание объектов с
.createObject(null)
в моем коде. Это чистое любопытство.
Вы пытались сделать это, установив вновь созданный объект в обычное свойство? Мое предположение было бы в том, что свойство 'children' отличается от другого, поскольку оно имеет другую семантику. –
Не имеет значения, ref counting должен работать в любом случае. – dtech
@ddriver Мое предположение заключается в том, что движок QML ожидает, что объект будет находиться под правами сценария, поскольку он не имеет родителя, но на самом деле находится под лицензией C++, т. Е. Удаляется с помощью 'children'. Следовательно, рекомендуется попробовать с единственным свойством объекта, чтобы проверить, является ли это обычным «без родительского элемента, а также не помечено для владельца C++, но удалено в C++». –