开篇
性能优化在行业里永远是一个常谈的话题,该话题里的内容无法用准则来描述啦,而更多的是建议和规则。本文多数内容、观点和建议参考于Qt官方资料并结合自己的实际QML使用习惯总结而成。优化规则并不是“黄金规则”,更不是“金标准”。对于QML应用开发来说,将这些规则根据具体应用场景能合理运用即可啦。
本文内容主要涉及到:Text元素、Image元素、模型视图和视觉效果四个方面的一些优化规则和推荐实践。
性能优化 | Text元素
计算文本的布局会是一个缓慢的操作。所以,在实际开发中尽可能优先考虑使用明文格式,而不是StyledText
,这可以减少布局引擎的工作量。如果不能使用明文(例如:需要嵌入图像,或使用标记来指定具有特定格式(粗体、斜体等)的字符范围),那么才考虑使用StyledText
。
应该只在文本可能是StyledText的情况下使用AutoText,因为这种模式会导致很高的解析成本。除此之外,还不应该使用RichText模式,因为StyledText几乎提供了其所有的特性。
性能优化 | Image元素
在任何软件的用户界面中,图片都是重要组成部分。但是一般加载图片所需的时间、消耗的内存数量和使用方式,都会影响应用程序的性能,在本小结中,描述在实际qml应用开发中,在使用图片时关于性能的几条优化点。
异步加载图片
图片通常非常大,所以最佳的做法是确保加载图片不会阻塞UI线程。将Image元素的asynchronous
属性设置为true,用于允许从本地文件系统异步加载图片(注:远程图片总是异步加载的)。
注:当
asynchronous
属性设置为true时,图片元素将在低优先级的工作线程中加载。
显式设置图片源的属性
如果在应用程序中加载了一个大尺寸的图片,但是却在一个小尺寸的元素中显示它,因此我们应该设置图片的sourceSize
属性为被呈现的元素的大小,以确保在内存中保存的是小尺寸的图片,而不是大尺寸的图片。
注:更改sourceSize会导致图像重新加载。
避免运行时拼接
通过在应用程序中提供预合成的图片资源(例如,提供带有阴影效果的元素),可以避免在运行时进行图片合成。
避免平滑图片
对于Image类型,image.smotth
用于设置图片的平滑参数,我们在需要时才进行平滑操作。因为在一些硬件上进行图片平滑速度较慢,而且如果图像以原图大小显示,则没有视觉效果,因此也没有意义且影响性能。
避免多次绘制
避免在一个区域多次绘制。在设计qml文件时,使用Item
作为根元素,而不要使用Rectangle
,以避免多次绘制背景。
性能优化 | 使用Anchor定位元素
使用锚定位比使用绑定更有效率。例如下列代码,
Rectangle{
id:rect1
x:20
width:200;height:200
}
Rectangle{
id:rect2
x:rect1.x
y:rect1.y+rect1.height
width:rect1.width-20
height:200
}
在上述代码中,是使用使用绑定来定位rect2相对于rect1的位置。从性能角度来看,更高效的做法是:
Rectangle{
id:rect1
x:20
width:200;height:200
}
Rectangle{
id:rect2
height:200
anchors.left:rect1.left
anchors.top:rect1.bottom
anchors.right:rect1.right
anchors.rightMargin:20
}
使用绑定定位(通过将绑定表达式赋值给可视对象的x、y、widht和height属性)相对较慢,但是这种方式具有灵活性的优点。
如果布局不是动态的,指定布局最有效的方法是静态初始化x, y, width和height属性。Item坐标总是相对于它们的父节点,所以如果想要与父节点的(0,0)坐标保持固定的偏移,就不能使用anchor。如下面的例子,子矩形对象位于相同的位置,但锚代码显示的效率不如通过静态初始化使用固定定位的代码:
Rectangle{
width:60
height:60
Rectangle{
id:fixedPositioning
x:20
y:20
width:20
height:20
}
Rectangle{
id:anchorPositioning
anchors.fill:parent
anchors.margins:20
}
}
性能优化 | 模型和视图
绝大多数的应用程序至少包含一个向视图提供数据的模型。但是如果数据量较大,将会影响性能,所以我们需要知道在实际开发中如何优化性能,本小节提供几条方法:
自定义C++模型
用C++编写我们的自定义模型,以便在QML中与视图一起使用。此类模型的最佳实现将在很大程度上取决于实际的应用场景,以下是几点准则:
(1)尽可能保持异步。
(2)保证所有的处理都在一个(低优先级)的工作线程中进行。
(3)尽可能在后台批处理操作,以减少I/O和IPC。
注意:建议使用低优先级的工作线程,以将GUI线程被饥饿的风险降到最低(因为这可能会极大程度上影响GUI体验效果)。除此之外,同步和锁机制可能是导致性能变慢的一个重要原因,因此应避免不必要的锁定。
ListModel QML类型
在QML中,优先使用ListModel
类型,用于向ListView
视图提供数据。该类型足以满足大多数的使用场景了,只要使用正确,ListMode
性能也相对较好。在使用中,应注意以下两点:
(1)在工作线程中填充
在JavaScript中,ListModel
元素可以被填充到一个(低优先级)的工作线程中。我们必须在WorkerScript中显式调用ListModel上的sync()
,以便将更改同步到主线程。
注,使用WorkerScript元素将导致创建一个单独的JavaScript引擎(因为JavaScript引擎是属于单个线程),这一点将增加内存使用量。然而,多个WorkerScript元素将使用同一个工作线程,因此一旦应用程序已经使用了一个WorkerScript元素,那么使用第二个或第三个WorkerScript元素对内存的影响就可以忽略不计了。
(2)不要使用动态元素
Qt Quick 2 ListModel中的性能优化主要来自:假定了对给定模型中单个元素中的类型不会更改,因此缓存性能将显著提高。如果类型可以从一个元素到另一个元素的动态变化,则不满足Qt Quick 2对ListModel的优化,而且模型的性能将会差一个数量级。
因此,在默认情况下动态类型是禁用的。必须专门设置模型的dynamicRoles
属性,才能启用动态类型(并承受随之而来的性能下降)。因此,如果可以重新设计应用程序来避免使用动态类型,则推荐不要使用动态类型而是去重新设计程序。
视图(View)
视图代理应尽可能简单。在代理中只放置需要QML来显示的必要信息,不是立即需要的附加信息和操作(例如:如果在单击时显示更多信息)应该在需要的时候才创建(即:延迟创建
)
在设计视图代理时需要注意以下几点:
(1)代理中的元素越少,在视图中创建的速度就越快,因此视图滚动的速度就越快,效果越好。
(2)减少代理中绑定的数量。推荐在代理中使用Anchor而不是绑定来进行相对定位。
(3)避免在代理中使用ShaderEffect
元素。
(4)不要在代理中启动Clipping。
可以设置一个视图的cacheBuffer
属性来允许异步创建和在可见区域外缓存代理。对于不简单且不太可能在单帧内创建的视图代理,推荐使用cacheBuffer
。
注:
cacheBuffer
是在内存中保留额外的代理。因此,利用cacheBuffer
获得的值必须与内存使用相平衡。应使用基准测试来找到用例的最佳值,因为使用cacheBuffer会增加内存压力,在极端情况下,会导致视图滚动帧率降低,出现卡顿现象!
性能优化 | 视觉效果
Qt Quick 2允许开发人员和设计人员创建高端的用户界面。因此流动性、动态转换和视觉效果等特性可以在应用程序中发挥巨大作用,但在QML中使用这些特性时必须谨慎,因为可能会影响性能。
动画
通常,动画化一个Item的属性会导致引用该属性的所有绑定都被重新计算。在属性动画过程中的属性绑定被重新计算在实际开发中是必须的;但在一些情况下,可以考虑最好在执行动画之前禁用绑定,然后在动画完成后重新分配绑定。
避免在动画期间运行JavaScript。例如:避免为x属性的动画运行复杂的JavaScript表达式。
在使用脚本动画时应注意,因为这些动画是在主线程中运行的(因此如果它们需要很长时间才能完成,就可能会导致一些动画帧缺失)。
粒子效果
在Qt Quick Particles模块中允许粒子效果无缝集成到用户界面中。每个平台都有不同的图形硬件功能,Particles模块无法将参数限制为硬件能够很好支持的情况。
如果渲染的粒子越多(它们越大),图形硬件就需要越快,才能以60帧/秒的速度渲染,更快的CPU速度才能渲染更多的粒子效果。
因此,在目标平台上测试所有的粒子效果就变得很重要了,用于评估在60fps下渲染的粒子数量和大小。
审核编辑 :李倩
-
图像
+关注
关注
2文章
1082浏览量
40394 -
模型
+关注
关注
1文章
3140浏览量
48673 -
线程
+关注
关注
0文章
504浏览量
19638
原文标题:QML性能优化 | 常见界面元素优化
文章出处:【微信号:嵌入式小生,微信公众号:嵌入式小生】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
相关推荐
评论