簡體   English   中英

為什么QML刪除我的C ++ ListView模型?

[英]Why is QML deleting my C++ ListView model?

我正在iOS 9上使用Qt 5.5.1嘗試將動態創建的QAbstractListModel分配給ListViewmodel屬性:

Window {
    ListView {
        model: api.model()
        delegate: delegate
    }
    Component {
        id: delegate
        Text { text: "Test" }
    }
}

api是使用setContextProperty分配給QML上下文的C++對象。 model方法是Q_INVOKABLE ,它返回QAbstractListModel * 所有這些都有效,我的ListView充滿了數據。

問題是當我開始滾動時。 通常在第二次完整滾動(到底部,再回到頂部並再次向下)之后,我的ListView開始清除。 調試器告訴我QAbstractListModel被銷毀。

我不想在模型上設置CppOwnership 還有另一種方法可以防止ListView破壞其模型嗎?

QML在這方面似乎有點破損,我經歷了在多種情況下仍在使用的對象的完全任意刪除。 帶有父對象並被JS引擎引用的對象沒有明顯原因被刪除,而JS垃圾仍然占用數百兆的內存而不是被釋放。 這適用於從C ++返回的對象和在QML中創建的對象。 當對象從C ++函數返回到QML時,所有權將傳遞給QML引擎,這使對象容易受到此類任意刪除的攻擊。

解決方案是強制CPP所有權並手動管理對象的生存期-請記住destroy()在此類對象上不起作用,因此您必須使用QML中的C ++函數將其刪除。

qmlEngine.setObjectOwnership(obj, QQmlEngine::CppOwnership);

另外,正如BaCaRoZzo所述,將模型作為屬性公開給api可能是合適的形式。 它取決於函數是僅僅是現有對象的訪問器,還是它自己創建對象。

無論如何,請記住,此時不能也不應該信任QML對象生存期管理。

即使我接受了ddriver的回答,我ddriver找到了一個似乎更符合我想要的解決方案。

通過動態加載組件並將模型存儲為變量,我可以獲得QML使我的C++模型保持活動狀態並在需要時銷毀它們,例如:

MyComponent {
    property var model: api.createModel()

    ListView {
        model: model
        delegate: delegate
        [...]
    }

    Component { id: delegate [...] }

    Component.onDestruction: model.destroy()
}

不幸的是,似乎需要對model.destroy()調用。 我原本希望垃圾收集器來處理此問題,但事實並非如此。

到目前為止,我只測試了這是玩具示例,請注意。

只能說-我可以在Linux x86_64和Android ARMv7上確認相同的問題。

MyComponent {
    property var model: api.createModel()

    ListView {
        model: model
        delegate: delegate
        [...]
    }

    Component { id: delegate [...] }
}

如果您不介意稍后銷毀模型,似乎就足夠了。

我想在ddriver的答案中添加一些內容,這不僅僅是評論。

我也遇到了同樣的問題。 基本上,我想創建一個動態列表視圖模型(實際上是QAbstractListModel)。 通常的方法是像這樣將模型放在主要(或某個地方)的前面:

QQmlContext* ctxt = engine.rootContext();
ctxt->setContextProperty("myModel",  &model);

在這種情況下, 每個對象只有一個模型,因此我需要一個動態解決方案。

我有一個QObject可以為列表創建模型。 創建的模型源自QAbstractListModel 我的QObject主機使用Q_INVOKABLE創建並給出了模型。

第一個問題是這樣生成的模型的類型未知,必須注冊。 通常的qmlRegisterType不起作用,因為無法復制QAbstractListModels。 因此,您必須使用qmlRegisterUncreatableType注冊。

那是第一位。 現在該模型有效, 誰將其銷毀?

事實證明,由於所有權是作為Q_INVOKABLE訪問器的一部分隱式賦予QML的,因此我的C ++代碼 QML都試圖破壞對象。

但是僅僅讓QML清理是不好的。 我跟蹤了什么時候發生,而根本沒有及時發生。 基本上,除非我做一些相當大的事情,例如調整窗口大小,否則它不會清理。 大概最終會清理掉(垃圾等),但是我真的希望這些動態模型在其宿主QObject出現故障時被清理掉。

ddriver的想法就是這樣。 但也要記得向qmlRegisterUncreatableType注冊。

例如,

inline MyModel* MyHostObject::getModel()
{
   if (!_model)
   {
     _model = new MyModel(this);

    // retain ownership of this object.
    QQmlEngine::setObjectOwnership(_model, QQmlEngine::CppOwnership);
   }
return _model;

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM