1

我从文件系统中加载了一个已更改的 qml 文件,但是由于第一次加载它,它也被缓存,即使Loader通过将源组件设置为“重置”它也不会刷新undefined

之前也有人问过类似的问题,但是出于以下几个原因,我想更进一步:

  • 那里接受的回答建议engine->trimComponentCache()不幸的是使用它只工作一次然后停止,没有进一步的更新反映
  • 在下面的评论中,OP 建议engine->clearComponentCache()每次都有效,而且确实有效。然而,这个方法的文档让我对它的用法有点不安:

此函数会导致引擎先前加载的所有组件的属性元数据被销毁。所有先前加载的组件以及从这些组件创建的所有现存对象的属性绑定都 将停止运行

这听起来很不祥,尤其是粗体部分,因为我没有重新加载我的整个应用程序,它只是一个相当大的应用程序的一小部分,它需要保持完整,同时刷新那个特定的外部 qml 文件反映其变化。

第二部分你听起来更有希望:

此函数将引擎返回到不包含任何加载的组件数据的状态。这对于重新加载先前组件集的较小子集或加载先前加载的组件的新版本可能很有用。

清除组件缓存后,必须先加载组件,然后才能创建任何新对象。

所以它确实给人的印象是这个方法可以用来只重新加载一个子集而不会破坏现有的代码。然而,即使是这样,也需要大量额外的工作来为新实例化的对象重建所有缓存,而不是简单地为更改的特定 qml 源清理缓存。

此外,我一直在考虑一个更复杂的解决方案,包括创建一个自定义 QML 元素,它本质上是一个围绕一个全新 QML 引擎的包装器,它呈现给 FBO 并将输出显示为我的“主”中的一个对象发动机,从而完全隔离两个发动机。但是,我并不热衷于做所有额外的工作,并引入另一个完整运行引擎的开销。

那么有什么想法吗?

4

1 回答 1

1

在有人提出更好的解决方案之前,我同时发现trimComponentCache()只有在清除、修剪和重置顺序发生时才会失败,即在同一个事件循环周期中。如果允许事件循环在两者之间旋转,它每次都有效,所以我选择了这个解决方案,它每次都有效:

  Timer {
    id: updater
    interval: 1
    repeat: true
    property int s: 0
    onTriggered: {
      switch (s) {
      case 0:
        loader.sourceComponent = undefined
        ++s
        break
      case 1:
        Aux.trim()
        ++s
        break
      case 2:
        loader.source = "file:/d:/Rect.qml"
        s = 0
        stop()
      }
    }
  }

所以更新是通过启动定时器发出的,它会在一个周期内清除加载器,在下一个周期修剪缓存,并重新加载源并在最后一个停止,重置加载器及其状态。

于 2017-08-04T10:44:23.613 回答