Skip to content

fix: reduce fullscreen page flip stutter by async icon loading#726

Merged
deepin-bot[bot] merged 1 commit intolinuxdeepin:masterfrom
Ivy233:fix/fullscreen-page-flip-stutter
Mar 9, 2026
Merged

fix: reduce fullscreen page flip stutter by async icon loading#726
deepin-bot[bot] merged 1 commit intolinuxdeepin:masterfrom
Ivy233:fix/fullscreen-page-flip-stutter

Conversation

@Ivy233
Copy link
Contributor

@Ivy233 Ivy233 commented Mar 9, 2026

Set asynchronous: true on the Loader in IconItemDelegate to defer DciIcon instantiation across multiple frames. This prevents the synchronous creation of all icon components (22-32 per page) from blocking the main thread during page transitions, reducing the maximum single-frame stall from ~100ms to ~34ms.

Log: Fix fullscreen launcher page flip animation stutter

Influence:

  1. Fullscreen launcher page flip animation smoothness
  2. Icon display when scrolling to a new page

fix: 通过异步加载图标减少全屏翻页卡顿

在 IconItemDelegate 的 Loader 上设置 asynchronous: true,将 DciIcon 的实例化分散到多个帧完成。避免翻页时每页 22-32 个图标组件在同一帧内同步
创建导致主线程阻塞,最大单帧卡顿从约 100ms 降低到约 34ms。

Log: 修复全屏启动器翻页动画卡顿问题

Influence:

  1. 全屏启动器翻页动画流畅度
  2. 滚动到新页面时的图标显示

PMS: BUG-352045

Summary by Sourcery

Reduce main-thread blocking during fullscreen launcher page flips by making icon loading asynchronous in the icon delegate.

Bug Fixes:

  • Improve fullscreen launcher page flip animation smoothness by deferring icon instantiation across multiple frames.

Enhancements:

  • Load icon components asynchronously in the icon delegate to reduce single-frame stalls when navigating to new pages.

Set asynchronous: true on the Loader in IconItemDelegate to defer
DciIcon instantiation across multiple frames. This prevents the
synchronous creation of all icon components (22-32 per page) from
blocking the main thread during page transitions, reducing the
maximum single-frame stall from ~100ms to ~34ms.

Log: Fix fullscreen launcher page flip animation stutter

Influence:
1. Fullscreen launcher page flip animation smoothness
2. Icon display when scrolling to a new page

fix: 通过异步加载图标减少全屏翻页卡顿

在 IconItemDelegate 的 Loader 上设置 asynchronous: true,将 DciIcon
的实例化分散到多个帧完成。避免翻页时每页 22-32 个图标组件在同一帧内同步
创建导致主线程阻塞,最大单帧卡顿从约 100ms 降低到约 34ms。

Log: 修复全屏启动器翻页动画卡顿问题

Influence:
1. 全屏启动器翻页动画流畅度
2. 滚动到新页面时的图标显示

PMS: BUG-352045
@sourcery-ai
Copy link

sourcery-ai bot commented Mar 9, 2026

Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Sets the icon Loader in IconItemDelegate to load its source component asynchronously so DciIcon instances are created over multiple frames instead of blocking a single frame during fullscreen launcher page flips.

Sequence diagram for asynchronous icon loading during fullscreen page flip

sequenceDiagram
  title Asynchronous icon loading during fullscreen page flip
  actor User
  participant FullscreenLauncher
  participant IconItemDelegate
  participant iconLoader
  participant QmlEngine
  participant DciIcon

  User->>FullscreenLauncher: Swipe to next page
  FullscreenLauncher->>IconItemDelegate: Request icons for new page
  IconItemDelegate->>iconLoader: Set sourceComponent
  IconItemDelegate->>iconLoader: Set asynchronous true
  iconLoader->>QmlEngine: Schedule DciIcon instantiation
  loop Multiple frames
    QmlEngine-->>iconLoader: Create next DciIcon instance
    iconLoader-->>DciIcon: Instantiate and bind data
    DciIcon-->>FullscreenLauncher: Icon rendered on page
  end
  FullscreenLauncher-->>User: Smooth page flip animation with progressively appearing icons
Loading

Class diagram for IconItemDelegate and asynchronous icon Loader

classDiagram
  class IconItemDelegate {
    +icons
  }

  class Loader_iconLoader {
    +asynchronous bool
    +sourceComponent
    +loadSourceComponent()
  }

  class DciIcon {
    +imageSource
    +label
  }

  IconItemDelegate *-- Loader_iconLoader : contains
  Loader_iconLoader *-- DciIcon : loads asynchronously
Loading

File-Level Changes

Change Details Files
Make icon component loading asynchronous to reduce main-thread stalls during fullscreen page flips.
  • Enable asynchronous loading on the Loader used for icons so component instantiation is spread across multiple frames.
  • Keep the existing logic for choosing between folderComponent and imageComponent as the Loader sourceComponent.
  • Leave drag handling and layout bindings unchanged so behavior other than load timing remains the same.
qml/IconItemDelegate.qml

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've reviewed your changes and they look great!


Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@deepin-ci-robot
Copy link

deepin pr auto review

这段代码在 qml/IconItemDelegate.qml 文件中为 Loader 组件添加了 asynchronous: true 属性。以下是对此修改的详细审查意见:

1. 语法逻辑

  • 审查结果:通过
  • 分析Loader 组件确实拥有 asynchronous 属性,将其设置为 true 在语法上是完全正确的。这意味着加载器会尝试异步加载组件。

2. 代码质量

  • 审查结果:良好
  • 分析
    • 意图明确:添加此属性的意图很明确,即为了防止在加载组件(尤其是复杂的 QML 组件)时阻塞 UI 线程。
    • 适用场景IconItemDelegate 通常用于列表视图(如 ListView 或 GridView)中。如果列表项很多,或者 sourceComponent 指向的组件(folderComponentimageComponent)比较复杂,同步加载可能会导致滚动卡顿。开启异步加载可以显著提升流畅度。
    • 潜在风险:异步加载会导致组件在加载完成前不可见。对于图标项来说,这通常是可以接受的(用户可能会短暂看到一个占位符或空白),但在某些严格要求即时显示的场景下需要权衡。

3. 代码性能

  • 审查结果:优秀
  • 分析
    • UI 响应性:这是此修改带来的最大收益。通过将组件加载放到后台线程,主 UI 线程可以继续处理用户输入和动画,从而避免界面冻结。
    • 资源加载:如果 imageComponent 涉及网络图片或大尺寸本地图片的解码,异步加载能极大地改善体验。

4. 代码安全

  • 审查结果:通过
  • 分析:此修改不涉及数据处理、权限控制或网络请求等安全敏感领域,因此不会引入新的安全漏洞。

改进建议与注意事项

虽然这个改动总体上是积极的,但在实际应用中建议注意以下几点:

  1. 加载状态反馈
    由于开启了异步加载,组件不会立即出现。建议添加一个加载状态的指示(如 Loader.onStatusChanged),或者设置一个简单的默认 sourceComponent 作为占位符,避免用户看到闪烁或空白区域。

    Loader {
        id: iconLoader
        anchors.fill: parent
        asynchronous: true
        // 可选:设置一个占位组件,防止加载时的空白闪烁
        // sourceComponent: root.icons !== undefined ? folderComponent : imageComponent
        
        // 监听加载状态
        onStatusChanged: {
            if (status === Loader.Loading) {
                // 可以在这里显示加载动画或占位符
            }
        }
    }
  2. 组件大小计算
    异步加载的组件在加载完成之前,其 widthheight 可能为 0 或未定义。如果布局依赖于 Loader 及其子组件的尺寸,请确保布局系统(如 anchors.fill: parent 或父级的布局策略)能够正确处理这种尺寸变化,避免布局抖动。

  3. 源组件类型
    asynchronous 属性对于 source(URL)和 sourceComponent(Component 对象)的行为略有不同。

    • 如果是 source(加载 QML 文件),它是真正的异步编译和加载。
    • 如果是 sourceComponent(如代码中所示),由于组件定义可能已经被编译,"异步"主要体现在实例化的过程中。虽然仍有性能提升,但对于非常简单的组件,效果可能不如加载外部文件明显。不过,考虑到 folderComponent 可能包含子元素,此优化依然有效。

总结
这是一个针对性能优化的良好改动,能够有效提升大量图标项渲染时的 UI 流畅度。建议配合简单的加载状态处理或占位符,以获得最佳的用户体验。

Copy link
Member

@BLumia BLumia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

印象里之前启动器用的是 Image + asynchronous 然后还被提过单子或者反馈说打开的时候不会直接显示所有图标,不过印象里当时讨论的结论是就该这样。

@deepin-ci-robot
Copy link

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: BLumia, Ivy233

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@Ivy233
Copy link
Contributor Author

Ivy233 commented Mar 9, 2026

/forcemerge

@deepin-bot deepin-bot bot merged commit 32f38a4 into linuxdeepin:master Mar 9, 2026
11 checks passed
@Ivy233 Ivy233 deleted the fix/fullscreen-page-flip-stutter branch March 9, 2026 08:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants