如何最正确/有效地刷新源已更改的项目?

时间:2017-08-04 09:02:20

标签: qt caching qml qqmlcomponent qqmlengine

我从文件系统中加载了一个qml文件,但是自从第一次加载它以来它也被缓存,即使Loader是"重置&也不会刷新#34;通过将源组件设置为undefined

similar questions has been asked before,但我想进一步说明原因:

  • 接受的答案建议使用engine->trimComponentCache()但遗憾的是只使用一次然后停止,没有进一步的更新反映
  • 在下面的评论中,OP建议engine->clearComponentCache()每次都有效,事实确实如此。但是,这种方法的文档让我对它的用法有点不安:
  

此函数会导致所有组件的属性元数据   以前被发动机装载要被摧毁。所有以前加载   组件和所有现有对象的属性绑定   来自这些组件的将停止运作

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

第二部分你听起来更有说服力:

  

此函数将引擎返回到不包含的状态   任何加载的组件数据。这可能有助于重新加载   上一个组件集的较小子集,或加载新版本   以前加载的组件。

     

清除组件缓存后,必须加载组件   在创建任何新对象之前。

因此,它确实给人的印象是此方法只能用于重新加载子集而不会破坏现有代码。但是,即使是这种情况,也需要进行大量额外工作来重建新实例化对象的所有缓存,而不是简单地清理缓存以更改特定的qml源。

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

所有想法?

1 个答案:

答案 0 :(得分: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()
      }
    }
  }

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