【鴻蒙HarmonyOS Next實戰開發】實現組件動態創建和卸載-優化性能

一、簡介

為了解決頁面和組件加載緩慢的問題,ArkUI框架引入了動態操作功能,支持組件的預創建,并允許應用在運行時根據實際需求動態加載和渲染組件。

這些動態操作包括動態創建組件(即動態添加組件)動態卸載組件(即動態刪除組件)

動態創建組件是指在build生命周期之外提前創建組件,這種方式不僅能節省組件創建時間,提升用戶體驗,還能將獨立邏輯封裝起來,助力應用的模塊化開發。

而動態卸載組件則是對動態創建的組件進行卸載和刪除操作。

二、組件預創建原理

在傳統的聲明式開發范式中,組件僅在build階段被創建,開發者無法在其他生命周期階段進行組件創建,這往往會導致頁面加載速度較慢。

然而,ArkUI框架提供的UI動態操作支持組件的預創建,允許開發者在非build生命周期階段提前創建組件。這些預創建的組件可以在頁面加載時直接使用,從而大幅提升頁面的響應速度

如圖1所示,利用組件預創建機制,可以在動畫執行過程中的空閑時間進行組件預創建和屬性設置。當動畫結束后,再進行屬性和布局的更新,從而節省組件創建時間,加快頁面渲染速度

圖1組件預創建原理圖?

三、FrameNode自定義節點在動態布局場景下的優勢
1.減少自定義組件創建開銷


在聲明式開發范式中,使用ArkUI的自定義組件對節點樹中的每個節點進行定義時,往往會遇到節點創建效率低下的問題。

這是因為在ArkTS引擎中,每個節點都需要分配內存空間來存儲應用程序的自定義組件和狀態變量,并且在節點創建過程中還需執行組件ID、組件閉包以及狀態變量之間的依賴關系收集等操作。相比之下,使用ArkUI的FrameNode可以避免創建自定義組件對象和狀態變量對象,無需進行依賴收集,從而顯著提升組件創建速度。

2.組件更新更快


在動態布局框架的更新場景中,通常存在一個由樹形數據結構ViewModelA創建的UI組件樹TreeA。當需要使用新的數據結構ViewModelB來更新TreeA時,盡管聲明式開發范式可以實現數據驅動的自動更新,但這一過程中伴隨著大量的diff操作。

對于ArkTS引擎而言,在對一個復雜組件樹(深度超過30層,包含100至200個組件)執行diff算法時,幾乎無法在120Hz的刷新率下保持滿幀運行。然而,使用ArkUI的FrameNode擴展,框架能夠自主掌控更新流程,實現高效的按需剪枝。特別是對于那些僅服務于少數特定業務的動態布局框架,利用這一擴展可以實現快速的更新操作。

3.直接操作組件樹


在聲明式開發范式中,組件樹結構更新操作較為困難。例如,將組件樹中的一個子樹從當前子節點完整移到另一個子節點時,聲明式開發范式無法直接調整組件實例的結構關系,只能通過重新渲染整棵組件樹來實現。

而使用ArkUI的FrameNode擴展,則可以通過操作FrameNode輕松操控該子樹,將其移植到另一個節點,從而實現局部渲染刷新,性能更優。

四、組件動態添加、更新和刪除
1、動態添加組件


動態添加組件的過程包括以下步驟:

  1. 創建自定義節點。

  2. 實現NodeController,用于管理自定義節點的創建、顯示、更新等操作,并負責將自定義節點掛載到NodeContainer上。

  3. 實現NodeController的makeNode方法,該方法會在NodeController實例綁定NodeContainer時被回調,并將返回的節點掛載至NodeContainer。

  4. 使用NodeContainer顯示自定義節點。

2、創建自定義節點


首先,準備好需要掛載的節點,代碼如下所示:

import { BuilderNode, FrameNode, NodeController } from '@kit.ArkUI';class Params {text: string = 'Hello World';constructor(text: string) {this.text = text;}
}@Builder
function buildText(params: Params) {Column() {Text(params.text).fontSize(50).fontWeight(FontWeight.Bold).margin({bottom: 36})}
}
3、實現NodeController


NodeController是一個抽象類,需要繼承并實現它,代碼如下所示:

class TextNodeController extends NodeController {private textNode: BuilderNode<[Params]> | null = null;private message: string = '';constructor(message: string) {super();this.message = message;}makeNode(context: UIContext): FrameNode | null {return null;}
}
4、實現NodeController的makeNode方法


首先,使用構造函數創建BuilderNode實例。創建BuilderNode對象時,必須傳入對應的UIContext對象。如果BuilderNode作為RenderNode的子節點存在,則需要設置RenderOptions的selfIdealSize屬性。然后,使用BuilderNode的build方法構建組件樹。build()方法需要傳入兩個參數:第一個參數是通過wrapBuilder()封裝的全局@Builder方法;第二個參數是對應的@Builder方法所需的參數對象。如果@Builder方法不帶參數或者存在默認參數,則build()的第二個參數可以省略。

class TextNodeController extends NodeController {private textNode: BuilderNode<[Params]> | null = null;private message: string = '';constructor(message: string) {super();this.message = message;}makeNode(context: UIContext): FrameNode | null {this.textNode = new BuilderNode(context);this.textNode.build(wrapBuilder<[Params]>(buildText), new Params(this.message));return this.textNode.getFrameNode();}
}
5、顯示自定義節點


顯示自定義節點依賴于聲明式渲染容器NodeContainer和對應的控制類NodeController。NodeController的makeNode方法返回的節點會顯示在對應的NodeContainer中。由于makeNode需要返回一個FrameNode,因此如果預期顯示BuilderNode,需要調用BuilderNode的getFrameNode方法來獲取其根節點。詳細代碼如下:

@Entry
@Component
struct Index {@State message: string = "hello";private textNodeController: TextNodeController = new TextNodeController(this.message);build() {Row() {Column() {NodeContainer(this.textNodeController).width('100%').height(100).backgroundColor('#FFF0F0F0')}.width('100%').height('100%')}.height('100%')}
}
6、更新自定義節點


更新自定義節點可以參考BuilderNode的update方法。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/895468.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/895468.shtml
英文地址,請注明出處:http://en.pswp.cn/news/895468.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【未完待續】關于I-Cache的一些思考

前言 最近對計組重拾興趣&#xff0c;想到了一些問題&#xff0c;本來想著會不會存在一些漏洞的&#xff0c;但是查閱資料發現還是自己太年輕了&#xff0c;架構師們早就想到了這些問題。這里簡單記錄一些與 GPT 的對話。感興趣的同學可以自行思考或查閱資料學習 與 GPT 的對…

MongoDB 7 分片副本集升級方案詳解(上)

#作者&#xff1a;任少近 文章目錄 前言&#xff1a;Mongodb版本升級升級步驟環境1.1環境準備1.2standalone升級1.3分片、副本集升級 前言&#xff1a;Mongodb版本升級 在開始升級之前&#xff0c;請參閱 MongoDB下個版本中的兼容性變更文檔&#xff0c;以確保您的應用程序和…

AI前端開發:跨領域合作的新引擎

隨著人工智能技術的飛速發展&#xff0c;AI代碼生成器等工具的出現正深刻地改變著軟件開發的模式。 AI前端開發的興起&#xff0c;不僅提高了開發效率&#xff0c;更重要的是促進了跨領域合作&#xff0c;讓數據科學家、UI/UX設計師和前端工程師能夠更緊密地協同工作&#xff0…

前端開發所需參考文檔—重中之中

菜鳥教程&#xff1a;https://www.runoob.com/ W3C&#xff1a;https://www.w3school.com.cn/index.html MMDN&#xff1a;https://developer.mozilla.org/zh-CN/ Vue3&#xff1a;Vue.js - 漸進式 JavaScript 框架 | Vue.js 基本上所有的前端開發基礎都可以在其中找到參考…

DeepSeek 助力 Vue 開發:打造絲滑的返回頂部按鈕(Back to Top)

前言&#xff1a;哈嘍&#xff0c;大家好&#xff0c;今天給大家分享一篇文章&#xff01;并提供具體代碼幫助大家深入理解&#xff0c;徹底掌握&#xff01;創作不易&#xff0c;如果能幫助到大家或者給大家一些靈感和啟發&#xff0c;歡迎收藏關注哦 &#x1f495; 目錄 Deep…

C++中接口與繼承的區別(自我學習用)

繼承&#xff08;Inheritance&#xff09;和 接口&#xff08;Interface&#xff09;是面向對象編程&#xff08;OOP&#xff09;中的兩種不同概念&#xff0c;雖然在 C 中沒有像 Java 那樣的 interface 關鍵字&#xff0c;但可以通過 純虛函數 來實現接口的概念。讓我們詳細比…

epoll的原理

Epoll是Linux系統中高效的I/O多路復用機制&#xff0c;廣泛應用于高并發服務器&#xff08;如Nginx、Redis&#xff09;。其核心原理在于事件驅動模型和高效數據結構設計&#xff0c;解決了傳統select/poll的性能瓶頸。以下從數據結構、工作流程、觸發模式等維度展開分析&#…

epoll_ctl的概念和使用案例

epoll_ctl 是 Linux 系統中 I/O 多路復用機制 epoll 的核心函數之一&#xff0c;用于管理 epoll 實例監控的文件描述符&#xff08;File Descriptor, FD&#xff09;。它負責向 epoll 實例注冊、修改或刪除需要監控的 FD 及其事件類型&#xff0c;是實現高性能網絡編程&#xf…

Java練習(20)

ps:練習來自力扣 給你一個 非空 整數數組 nums &#xff0c;除了某個元素只出現一次以外&#xff0c;其余每個元素均出現兩次。找出那個只出現了一次的元素。 你必須設計并實現線性時間復雜度的算法來解決此問題&#xff0c;且該算法只使用常量額外空間。 class Solution {pu…

Tetragon:一款基于eBPF的運行時環境安全監控工具

關于Tetragon Tetragon是一款基于eBPF的運行時環境安全監控工具&#xff0c;該工具可以幫助廣大研究人員檢測并應對安全重大事件&#xff0c;例如流程執行事件、系統調用活動、I/O活動&#xff08;包括網絡和文件訪問等&#xff09;。 在 Kubernetes 環境中使用時&#xff0c;…

1046. 最后一塊石頭的重量

文章目錄 1.題目[1046. 最后一塊石頭的重量](https://leetcode.cn/problems/last-stone-weight/description/)2.思路3.代碼 1.題目 1046. 最后一塊石頭的重量 有一堆石頭&#xff0c;每塊石頭的重量都是正整數。 每一回合&#xff0c;從中選出兩塊** 最重的** 石頭&#xff…

Qt多線程技術【線程池】:QRunnable 和 QThreadPool

在現代軟件開發中&#xff0c;尤其是在處理大量并發任務時&#xff0c;線程池技術是一種高效的解決方案。線程池不僅能提高程序的性能&#xff0c;還能有效管理線程的生命周期&#xff0c;避免頻繁的線程創建和銷毀所帶來的性能損失。本文將以Qt中的 QThreadPool 和 QRunnable …

DOM讓JavaScript可以對文檔中的標簽、屬性、內容等進行 訪增刪改 操作

示例 HTML 文檔 首先&#xff0c;我們有一個簡單的 HTML 文件 index.html&#xff0c;內容如下&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widt…

218.子結構判斷

class Solution {/*** 判斷樹 B 是否是樹 A 的子結構* param A 樹 A 的根節點* param B 樹 B 的根節點* return 如果 B 是 A 的子結構&#xff0c;返回 true&#xff1b;否則返回 false*/public boolean isSubStructure(TreeNode A, TreeNode B) {// 如果樹 B 為空&#xff0c;…

【DuodooBMS】基于Odoo的開源制造執行系統——以開源之力,驅動智能制造

以用戶為中心的開放式智造平臺 DuodooMES的設計始終圍繞“用戶可編程、生態可生長”的核心思想&#xff0c;打破傳統工業軟件的封閉性&#xff0c;讓制造企業真正成為系統的“主人”&#xff1a; 1. 用戶可編程&#xff1a;生產流程由你定義 界面可配置&#xff1a;無需代碼即…

Unity使用iTextSharp導出PDF-02基礎結構及設置中文字體

基礎結構 1.創建一個Document對象 2.使用PdfWriter創建PDF文檔 3.打開文檔 4.添加內容&#xff0c;調用文檔Add方法添加內容時&#xff0c;內容寫入到輸出流中 5.關閉文檔 using UnityEngine; using iTextSharp.text; using System.IO; using iTextSharp.text.pdf; using Sys…

Navicat導入海量Excel數據到數據庫(簡易介紹)

目錄 前言正文 前言 此處主要作為科普帖進行記錄 原先Java處理海量數據的導入時&#xff0c;由于接口超時&#xff0c;數據處理不過來&#xff0c;后續轉為Navicat Navicat 是一款功能強大的數據庫管理工具&#xff0c;支持多種數據庫系統&#xff08;如 MySQL、PostgreSQL、…

文化財經t8優質短線期貨交易量化模型源碼

// 參數設置 BOLL_PERIOD : 20; // 布林帶周期 RSI_PERIOD : 14; // RSI 周期 OVERSOLD : 30; // 超賣線 OVERBOUGHT : 70; // 超買線 // 計算布林帶 MID : MA(CLOSE, BOLL_PERIOD); UPPER : MID 2 * STD(CLOSE, BOLL_PERIOD); LOWER : MID - 2 * STD(CLOSE,…

[AI]Mac本地部署Deepseek R1模型 — — 保姆級教程

[AI]Mac本地部署DeepSeek R1模型 — — 保姆級教程 DeepSeek R1是中國AI初創公司深度求索&#xff08;DeepSeek&#xff09;推出大模型DeepSeek-R1。 作為一款開源模型&#xff0c;R1在數學、代碼、自然語言推理等任務上的性能能夠比肩OpenAI o1模型正式版&#xff0c;并采用MI…

【UE5】PeerStream像素流部署

視頻教程 https://www.bilibili.com/video/BV1GhiuecEpK?spm_id_from333.788.videopod.sections&vd_source02dd8acc3a83a728e375ff61f1ebe725步驟 下載PeerStream代碼 代碼結構和項目如圖 github地址:https://github.com/inveta/PeerStreamEnterprise下載node node 對應…