百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

QML性能优化 | 常见界面元素优化

bigegpt 2024-08-22 10:50 4 浏览

1、开篇

性能优化在行业里永远是一个常谈的话题,该话题里的内容无法用准则来描述啦,而更多的是建议和规则。本文多数内容、观点和建议参考于Qt官方资料并结合自己的实际QML使用习惯总结而成。优化规则并不是“黄金规则”,更不是“金标准”。对于QML应用开发来说,将这些规则根据具体应用场景能合理运用即可啦。

本文内容主要涉及到:Text元素、Image元素、模型试图和视觉效果四个方面的一些优化规则和推荐实践。

2、性能优化 | Text元素

计算文本的布局会是一个缓慢的操作。所以,在实际开发中尽可能优先考虑使用明文格式,而不是StyledText,这可以减少布局引擎的工作量。如果不能使用明文(例如:需要嵌入图像,或使用标记来指定具有特定格式(粗体、斜体等)的字符范围),那么才考虑使用StyledText

还应该只在文本可能是StyledText的情况下使用AutoText,因为这种模式会导致很高的解析成本。除此之外,还不应该使用RichText模式,因为StyledText几乎提供了所有的特性。

3、性能优化 | Image元素

在任何软件的用户界面中,图片都是重要组成部分。但是一般加载图片所需的时间、消耗的内存数量和使用方式,都会影响应用程序的性能,在本小结中,描述在实际qml应用开发中,使用图片时关于性能方面的优化点。

3-1、异步加载图片

图片通常非常大,所以最佳的做法是确保加载图片不会阻塞UI线程。将Image元素的asynchronous属性设置为true,用于允许从本地文件系统异步加载图片(注:远程图片总是异步加载的)。

注:当asynchronous属性设置为true时,图片元素将在低优先级的工作线程中加载。

3-2、显式设置图片源的属性

如果在应用程序中加载了一个大尺寸的图片,但是却在一个小尺寸的元素中显示它,因此我们应该设置图片的sourceSize属性为被呈现的元素的大小,以确保在内存中保存的是小尺寸的图片,而不是大尺寸的图片。

注:更改sourceSize会导致图像重新加载。

3-3、避免运行时拼接

通过在应用程序中提供预合成的图片资源(例如,提供带有阴影效果的元素),可以避免在运行时进行图片合成。

3-4、避免平滑图片

对于Image类型,image.smotth用于设置图片的平滑参数,我们在需要时才进行平滑操作。因为在一些硬件上进行图片平滑速度较慢,而且如果图像以原图大小显示,则没有视觉效果,因此也没有意义且影响性能。

3-5、避免多次绘制

避免在一个区域多次绘制。在设计qml文件时,使用Item作为根元素,而不要使用Rectangle,以避免多次绘制背景。

4、性能优化 | 使用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、widthheight属性)相对较慢,但是这种方式具有灵活性的优点。

如果布局不是动态的,指定布局最有效的方法是静态初始化x, y, widthheight属性。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
    }
}

5、性能优化 | 模型和视图

绝大多数的应用程序至少包含一个向视图提供数据的模型。但是如果数据量较大,将会影响性能,所以我们需要知道在实际开发中如何优化性能,本小节提供几条方法:

5-1、自定义C++模型

用C++编写我们的自定义模型,以便在QML中与视图一起使用。此类模型的最佳实现将在很大程度上取决于实际的应用场景,以下是几点准则:

(1)尽可能保持异步。

(2)保证所有的处理都在一个(低优先级)的工作线程中进行。

(3)尽可能在后台批处理操作,以减少I/O和IPC。

注意:建议使用低优先级的工作线程,以将GUI线程被饥饿的风险降到最低(因为这可能会极大程度上影响GUI体验效果)。除此之外,同步和锁机制可能是导致性能变慢的一个重要原因,因此应避免不必要的锁定。

5-2、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属性,才能启用动态类型(并承受随之而来的性能下降)。因此,如果可以重新设计应用程序来避免使用动态类型,则推荐不要使用动态类型而是去重新设计程序。

5-3、视图(View)

视图代理应尽可能简单。在代理中只放置需要QML来显示的必要信息,不是立即需要的附加信息和操作(例如:如果在单击时显示更多信息)应该在需要的时候才创建(即:延迟创建

在设计视图代理时需要注意以下几点:

(1)代理中的元素越少,在视图中创建的速度就越快,因此视图滚动的速度就越快,效果越好。

(2)减少代理中绑定的数量。推荐在代理中使用Anchor而不是绑定来进行相对定位。

(3)避免在代理中使用ShaderEffect元素。

(4)不要在代理中启动Clipping。

可以设置一个视图的cacheBuffer属性来允许异步创建和在可见区域外缓存代理。对于不简单且不太可能在单帧内创建的视图代理,推荐使用cacheBuffer

注:cacheBuffer是在内存中保留额外的代理。因此,利用cacheBuffer获得的值必须与内存使用相平衡。应使用基准测试来找到用例的最佳值,因为使用cacheBuffer会增加内存压力,在极端情况下,会导致视图滚动帧率降低,出现卡顿现象!

6、性能优化 | 视觉效果

Qt Quick 2允许开发人员和设计人员创建高端的用户界面。因此流动性、动态转换和视觉效果等特性可以在应用程序中发挥巨大作用,但在QML中使用这些特性时必须谨慎,因为可能会影响性能。

6-1、动画

通常,动画化一个Item的属性会导致引用该属性的所有绑定都被重新计算。在属性动画过程中的属性绑定被重新计算在实际开发中是必须的;但在一些情况下,可以考虑最好在执行动画之前禁用绑定,然后在动画完成后重新分配绑定。

避免在动画期间运行JavaScript。例如:避免为x属性的动画运行复杂的JavaScript表达式。

在使用脚本动画时应注意,因为这些动画是在主线程中运行的(因此如果它们需要很长时间才能完成,就可能会导致一些动画帧缺失)。

6-2、粒子效果

在Qt Quick Particles模块中允许粒子效果无缝集成到用户界面中。每个平台都有不同的图形硬件功能,Particles模块无法将参数限制为硬件能够很好支持的情况。

如果渲染的粒子越多(它们越大),图形硬件就需要越快,才能以60帧/秒的速度渲染,更快的CPU速度才能渲染更多的粒子效果。

因此,在目标平台上测试所有的粒子效果就变得很重要了,用于评估在60fps下渲染的粒子数量和大小。

相关推荐

悠悠万事,吃饭为大(悠悠万事吃饭为大,什么意思)

新媒体编辑:杜岷赵蕾初审:程秀娟审核:汤小俊审签:周星...

高铁扒门事件升级版!婚宴上‘冲喜’老人团:我们抢的是社会资源

凌晨两点改方案时,突然收到婚庆团队发来的视频——胶东某酒店宴会厅,三个穿大红棉袄的中年妇女跟敢死队似的往前冲,眼瞅着就要扑到新娘的高额钻石项链上。要不是门口小伙及时阻拦,这婚礼造型团队熬了三个月的方案...

微服务架构实战:商家管理后台与sso设计,SSO客户端设计

SSO客户端设计下面通过模块merchant-security对SSO客户端安全认证部分的实现进行封装,以便各个接入SSO的客户端应用进行引用。安全认证的项目管理配置SSO客户端安全认证的项目管理使...

还在为 Spring Boot 配置类加载机制困惑?一文为你彻底解惑

在当今微服务架构盛行、项目复杂度不断攀升的开发环境下,SpringBoot作为Java后端开发的主流框架,无疑是我们手中的得力武器。然而,当我们在享受其自动配置带来的便捷时,是否曾被配置类加载...

Seata源码—6.Seata AT模式的数据源代理二

大纲1.Seata的Resource资源接口源码2.Seata数据源连接池代理的实现源码3.Client向Server发起注册RM的源码4.Client向Server注册RM时的交互源码5.数据源连接...

30分钟了解K8S(30分钟了解微积分)

微服务演进方向o面向分布式设计(Distribution):容器、微服务、API驱动的开发;o面向配置设计(Configuration):一个镜像,多个环境配置;o面向韧性设计(Resista...

SpringBoot条件化配置(@Conditional)全面解析与实战指南

一、条件化配置基础概念1.1什么是条件化配置条件化配置是Spring框架提供的一种基于特定条件来决定是否注册Bean或加载配置的机制。在SpringBoot中,这一机制通过@Conditional...

一招解决所有依赖冲突(克服依赖)

背景介绍最近遇到了这样一个问题,我们有一个jar包common-tool,作为基础工具包,被各个项目在引用。突然某一天发现日志很多报错。一看是NoSuchMethodError,意思是Dis...

你读过Mybatis的源码?说说它用到了几种设计模式

学习设计模式时,很多人都有类似的困扰——明明概念背得滚瓜烂熟,一到写代码就完全想不起来怎么用。就像学了一堆游泳技巧,却从没下过水实践,很难真正掌握。其实理解一个知识点,就像看立体模型,单角度观察总...

golang对接阿里云私有Bucket上传图片、授权访问图片

1、为什么要设置私有bucket公共读写:互联网上任何用户都可以对该Bucket内的文件进行访问,并且向该Bucket写入数据。这有可能造成您数据的外泄以及费用激增,若被人恶意写入违法信息还可...

spring中的资源的加载(spring加载原理)

最近在网上看到有人问@ContextConfiguration("classpath:/bean.xml")中除了classpath这种还有其他的写法么,看他的意思是想从本地文件...

Android资源使用(android资源文件)

Android资源管理机制在Android的开发中,需要使用到各式各样的资源,这些资源往往是一些静态资源,比如位图,颜色,布局定义,用户界面使用到的字符串,动画等。这些资源统统放在项目的res/独立子...

如何深度理解mybatis?(如何深度理解康乐服务质量管理的5个维度)

深度自定义mybatis回顾mybatis的操作的核心步骤编写核心类SqlSessionFacotryBuild进行解析配置文件深度分析解析SqlSessionFacotryBuild干的核心工作编写...

@Autowired与@Resource原理知识点详解

springIOCAOP的不多做赘述了,说下IOC:SpringIOC解决的是对象管理和对象依赖的问题,IOC容器可以理解为一个对象工厂,我们都把该对象交给工厂,工厂管理这些对象的创建以及依赖关系...

java的redis连接工具篇(java redis client)

在Java里,有不少用于连接Redis的工具,下面为你介绍一些主流的工具及其特点:JedisJedis是Redis官方推荐的Java连接工具,它提供了全面的Redis命令支持,且...