色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
电子发烧友
开通电子发烧友VIP会员 尊享10大特权
海量资料免费下载
精品直播免费看
优质内容免费畅学
课程9折专享价
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

鴻蒙跨端實踐-ArkTS和CAPI的混合開發實現

京東云 ? 來源:jf_75140285 ? 作者:jf_75140285 ? 2024-09-02 10:18 ? 次閱讀

一、背景

在動態化-鴻蒙跨端方案文章中,講述了動態化適配鴻蒙的方案實現,當在鴻蒙系統進行UI渲染的時候,我們使用了系統的組件進行遞歸渲染。在iOSAndroid也是借助各自系統組件進行的渲染,但是在鴻蒙系統會存在以下4個嚴重問題:

1. UI層級過多

以金融APP理財頻道頁中的一個樂高樓層中的“7天理財”文案為例,鴻蒙系統總計52層,iOS30層。層級過多會直接影響渲染性能,到達一定層級后會造成頁面掉幀和卡頓。

wKgZombVIH-AbkqAAATXo0dV640550.png

2. 通訊流程長

在實現鴻蒙跨端方案中,JS虛擬機(V8)運行JS代碼,通過JSI打通C++,再通過華為NAPI從C++打通ArkTS,跨語言通訊成本高。

wKgaombVIIGAA9j2AAEaQOLpxvw524.png

3. 列表渲染性能差

長列表渲染性能是iOS、Android、Harmony系統非常重要的指標,華為也一直在推出多種方案以提升列表渲染性能。但在業界所有三方框架渲染長列表復雜業務場景(例如社區頻道頁面)時,在ArkUI層因設計原理導致性能問題一直無法完美解決。

wKgZombVIIOAQgsEAAXIOCEXR0w854.png

4、二次布局

在對接到鴻蒙系統組件后,因為設置了相關布局屬性后,系統會進行二次布局。

二、新方案實踐

1.問題剖析

UI層級過多:原因在于在鴻蒙系統使用系統組件進行遞歸渲染的時候,需要借助自定義組件進行實現,然而和iOS和Android端的命令式組件渲染不同,比如RomaDiv對應iOS就是直接翻譯為UIView即可,在鴻蒙必須增加一個包裹的容器才是一個合法的自定義組件,比如Stack容器,這樣每個組件的層級就多了一層。

@Componentexport 
struct RomaDiv {
    build(){
        Stack(){
            //借助wrapBuilder實現遞歸
            ForEach(this.childrenTags, (childrenTag) => {
                  RomaComponentFactory.builder()//RomaComponentFactory就是對應鴻蒙系統提供的WrappedBuilder
            })
        }
    }
}

通訊流程長:js代碼運行在系統內置的V8虛擬機中,ArkTS代碼運行在華為的方舟虛擬機中,再加上V8運行js的線程,C++解析js指令的線程以及ArkTS的主線程,跨線程開銷耗時增加,以及各個語言間的數據類型轉換,通訊成本必然會非常高。

列表渲染性能差:鴻蒙的響應式編程,底層類似于vue做了依賴收集,雖然長列表場景下華為提供了cacheCount機制以提升列表渲染性能,但當數據發生變化的時候,數據的遞歸分析以及不在屏幕的的節點屬性設置直接導致了列表性能的大幅下降。

二次布局:動態化在鴻蒙系統的跨端已經集成了另外兩端共同使用的Yoga布局庫,其實在給華為系統組件設置屬性和坐標之前已經做好了布局計算,但是華為系統并未感知和處理這個過程,所以會存在二次布局的問題。

2.新方案簡介

針對以上問題,通過和華為溝通,鴻蒙系統提供了C語言的命令式接口。C組件接口是介于UI組件的Native實現和ArkTS對接層之間的一層C接口封裝,它繞過了狀態管理對組件變化、刷新的自動化管理,同時避免了JS引擎和C++之間類型轉換和跨語言調用的開銷,因此具有較好的性能。

通過C接口的對接,UI層級能直接和另外兩端基本一致,通訊過程直接從JS到C++,C++可以直接調用C接口,流程大大縮短,數據類型轉換變少了,列表渲染過程也由接入方自主控制,并且可以做預渲染等優化方案,同時避免了系統的二次布局。

wKgaombVIIOAOgw4AAB_uSC4Mg8553.png

3.如何使用

在實際的動態化鴻蒙跨端中,會存在ArkTS組件和C組件嵌套的場景(對于一些對性能影響較小的組件允許使用ArkTS),下面我們實現一個比較復雜的嵌套Demo,以展示整個嵌套實現過程。包含了ArkTS組件插入C組件、ArkTS組件插入ArkTS組件、C組件插入C組件、C組件插入ArkTS組件等場景。

wKgZombVIIWACw25AAJtauw4czg471.png

3.1、ArkTS插入C組件示例

ArkTS組件插入C組件的主要過程分為三步:

1、NodeContent管理器創建

2、build函數中的ContentSlot占位組件

3、NodeContent節點創建(CAPI)

import entry from 'libentry.so'; 
import { NodeContent } from '@ohos.arkui.node'

@Entry
@Component
struct CMixArkTS{ 
     //1、NodeContent管理器創建
     private divNodeContent: NodeContent = new NodeContent();
 }

build(){
    //2、build函數中的ContentSlot占位組件
    ContentSlot(this.divNodeContent);
}

aboutToAppear(): void {
    //3、NodeContent節點創建(CAPI)
    entry.CreateNativeDivNode(this.divNodeContent);
}

CreateNativeDivNode在C++中的實現如下:

此處有個坑:ArkUI_NativeNodeAPI_1 *nodeAPI 如果按照官方文檔代碼創建會失敗,正確的方法如下代碼所示。因為使用到ArkUI_NativeNodeAPI_1的地方比較多,所以我把ArkUI_NativeNodeAPI_1封裝到CAPIManager::getNodeAPI()方法中了。

這個過程的核心API為OH_ArkUI_NodeContent_AddNode(nodeContentHandle_, DivComponent); 第一個參數指向ArkTS側傳入的nodeContent,第二個參數就是使用CAPI創建的Div節點。

// 1、C組件-綠色邊框
static napi_value CreateNativeDivNode(napi_env env, napi_callback_info info) {
    // napi相關處理空指針&數據越界等問題
    if ((env == nullptr) || (info == nullptr)) {
        return nullptr;
    }

    napi_value returnVal = nullptr;

    size_t argc = 1;
    napi_value args[1] = {nullptr};
    if (napi_get_cb_info(env, info, &argc, args, nullptr, nullptr) != napi_ok) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "napi_init", "CreateNativeNode napi_get_cb_info failed");
    }

    if (argc != 1) {
        return nullptr;
    }
    // 將nodeContentHandle_指向ArkTS側傳入的nodeContent
    // 在Native側獲取ArkTS側Content指針。
    OH_ArkUI_GetNodeContentFromNapiValue(env, args[0], &nodeContentHandle_);

    // nodeAPI = reinterpret_cast(OH_ArkUI_QueryModuleInterfaceByName(ARKUI_NATIVE_NODE,
    // "ArkUI_NativeNode_API_1")); 上面寫法不行,必須如下寫法......
    // ArkUI_NativeNodeAPI_1 聲明 ArkUI 提供的原生節點 API 集合。 與原生節點相關的 API 必須在主線程中調用。
    // 包括創建節點、添加、刪除節點,給節點設置各種屬性樣式等
    static ArkUI_NativeNodeAPI_1 *nodeAPI = nullptr;
    if (nodeAPI == nullptr) {
        nodeAPI = reinterpret_cast(
            OH_ArkUI_QueryModuleInterfaceByName(ARKUI_NATIVE_NODE, "ArkUI_NativeNodeAPI_1"));
    }

    if (nodeAPI != nullptr) {
        if (nodeAPI->createNode != nullptr && nodeAPI->addChild != nullptr) {
            ArkUI_NodeHandle DivComponent;
            // 創建div節點
            DivComponent = CreateDivNodeHandle();
            // nodeContentHandle_指向ArkTS側傳入的nodeContent,nodeContent上div節點
            OH_ArkUI_NodeContent_AddNode(nodeContentHandle_, DivComponent);
        }
    }

    return returnVal;
}

static ArkUI_NodeHandle CreateDivNodeHandle() {
    ArkUI_NodeHandle greenDivNodeHandle;
    // 創建div的node
    greenDivNodeHandle = CreateDivNodeHandleWithParam(200, 0xFF00FF00);
    CAPIManager::GetInstance()->greenDivNodeHandle = greenDivNodeHandle;
    return greenDivNodeHandle;
}

static napi_value Init(napi_env env, napi_value exports){
    { "CreateNativeDivNode", nullptr, CreateNativeDivNode, nullptr, nullptr, nullptr, napi_default, nullptr},
}

真正的C組件創建:

static ArkUI_NodeHandle CreateDivNodeHandleWithParam(float height, uint32_t borderColor) {
 ArkUI_NodeHandle divNode = CAPIManager::getNodeAPI()->createNode(ArkUI_NodeType::ARKUI_NODE_FLEX);
 // margin
 ArkUI_NumberValue number = {.f32 = 5};
 ArkUI_AttributeItem marginValue = {
 .value = &number, // 初始化為NULL或者指向你的數字數組
 .size = 1, // 初始化為你的數字數組的大小
 .string = NULL, // 初始化為NULL或者指向你的字符串
 .object = NULL // 初始化為NULL或者指向你的對象
 };

 // borderWidth
 ArkUI_NumberValue number2 = {.f32 = 2};
 ArkUI_AttributeItem borderWValue = {
 .value = &number2, // 初始化為NULL或者指向你的數字數組
 .size = 1, // 初始化為你的數字數組的大小
 .string = NULL, // 初始化為NULL或者指向你的字符串
 .object = NULL // 初始化為NULL或者指向你的對象
 };

 // 背景色
 ArkUI_NumberValue number1 = {.u32 = borderColor};
 ArkUI_AttributeItem borderColorItem = {
 .value = &number1, // 初始化為NULL或者指向你的數字數組
 .size = 1, // 初始化為你的數字數組的大小
 .string = NULL, // 初始化為NULL或者指向你的字符串
 .object = NULL // 初始化為NULL或者指向你的對象
 };

 // 寬高
 ArkUI_NumberValue number3 = {.f32 = height};
 ArkUI_AttributeItem hValue = {
 .value = &number3, // 初始化為NULL或者指向你的數字數組
 .size = 1, // 初始化為你的數字數組的大小
 .string = NULL, // 初始化為NULL或者指向你的字符串
 .object = NULL // 初始化為NULL或者指向你的對象
 };
 ArkUI_NumberValue number5 = {.f32 = 0.9};
 ArkUI_AttributeItem wValue = {
 .value = &number5, // 初始化為NULL或者指向你的數字數組
 .size = 1, // 初始化為你的數字數組的大小
 .string = NULL, // 初始化為NULL或者指向你的字符串
 .object = NULL // 初始化為NULL或者指向你的對象
 };

 ArkUI_NumberValue number4 = {.i32 = ARKUI_ITEM_ALIGNMENT_CENTER};
 ArkUI_AttributeItem alignment = {
 .value = &number4, // 初始化為NULL或者指向你的數字數組
 .size = 1, // 初始化為你的數字數組的大小
 .string = NULL, // 初始化為NULL或者指向你的字符串
 .object = NULL // 初始化為NULL或者指向你的對象
 };
 // 屬性設置

 CAPIManager::getNodeAPI()->setAttribute(divNode, NODE_MARGIN, &marginValue);
 CAPIManager::getNodeAPI()->setAttribute(divNode, NODE_BORDER_WIDTH, &borderWValue);
 CAPIManager::getNodeAPI()->setAttribute(divNode, NODE_BORDER_COLOR, &borderColorItem);
 CAPIManager::getNodeAPI()->setAttribute(divNode, NODE_WIDTH_PERCENT, &wValue);
 CAPIManager::getNodeAPI()->setAttribute(divNode, NODE_HEIGHT, &hValue);
 CAPIManager::getNodeAPI()->setAttribute(divNode, NODE_ALIGN_SELF, &alignment);

 return divNode;
}

通過以上過程可以發現,通過CAPI創建一個節點并渲染的過程還是比較復雜的,但只要抓住實現過程的核心步驟,剩下的就是按照文檔開發就行了。

大家感受下iOS實現這個過程的模擬

- (UIView *) CreateNativeDivNode{
    UIView* div = [UIView new]; 
    div.backGroundColor = [UIColor greenColor];
    div.frame = CGRectMake(0,0,width,height);
    return div;
}

雖然過程有點復雜,但是效果還是不錯的,畢竟能解決文章開頭提出的4個問題。比如最直觀的UI層級,Text26(I am A ArkTS Node)的深度已經和其他兩端能對齊了。

wKgaombVIIWAehh9AAD7gAHUIv4803.png

3.2、其他場景實現

從上面ArkTS組件插入C組件一個過程實現能看到,代碼量還是比較驚人的,其他場景的實現讀者可以參考官方文檔進行嘗試。

審核編輯 黃宇

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 渲染
    +關注

    關注

    0

    文章

    74

    瀏覽量

    11047
  • CAPI
    +關注

    關注

    0

    文章

    5

    瀏覽量

    12541
  • 鴻蒙系統
    +關注

    關注

    183

    文章

    2638

    瀏覽量

    67273
  • 鴻蒙
    +關注

    關注

    57

    文章

    2459

    瀏覽量

    43462
收藏 0人收藏

    評論

    相關推薦

    鴻蒙實踐-JS虛擬機架構實現

    類似的框架,我們需要自行實現以確保核心基礎能力的完整。 鴻蒙虛擬機的開發經歷了從最初 ArkTs2V8 到 JSVM + Roma新架構方案 。在此過程中,我們
    的頭像 發表于 09-30 14:42 ?2711次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>跨</b><b class='flag-5'>端</b><b class='flag-5'>實踐</b>-JS虛擬機架構<b class='flag-5'>實現</b>

    鴻蒙OS開發實戰:【ArkTS 實現MQTT協議(2)】

    1. 協議傳輸通道僅為TCPSocket 2. 基于HarmonyOS SDK API 9開發 3. 開發語言:ArkTS,TypeScript
    的頭像 發表于 04-01 14:48 ?1825次閱讀
    <b class='flag-5'>鴻蒙</b>OS<b class='flag-5'>開發</b>實戰:【<b class='flag-5'>ArkTS</b> <b class='flag-5'>實現</b>MQTT協議(2)】

    鴻蒙實踐-布局方案介紹

    封裝到標簽中實現,業務只需要針對標簽簡單地設置相關屬性,即可實現列表類布局,大幅提升研發效率。同時動態化也支持絕對布局以及控制視圖的顯示和隱藏等功能,使之能勝任絕大多數業務布局場景。 在京東金融App使用動態化方案適配鴻蒙系統的
    的頭像 發表于 09-18 10:26 ?1121次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>跨</b><b class='flag-5'>端</b><b class='flag-5'>實踐</b>-布局方案介紹

    鴻蒙ArkTS的起源和簡介

    ,ArkTS也會結合應用開發及運行的其他方面需求持續演進: 更完善的類型系統 我們已經設計并實現了專門運行時,利用ArkTS的類型輸入,在程序執行一開始就獲得較高的運行性能(不像其它傳
    發表于 01-16 16:23

    鴻蒙語言ArkTS(更好的生產力與性能)

    ArkTS鴻蒙生態的應用開發語言 ArkTS提供了聲明式UI范式、狀態管理支持等相應的能力,讓開發者可以以更簡潔、更自然的方式
    發表于 02-17 15:56

    鴻蒙Flutter實戰:06-使用ArkTs開發Flutter鴻蒙插件

    # 使用 ArkTs 開發 Flutter 鴻蒙平臺插件 本文講述如何開發一個 Flutter 鴻蒙插件,如何
    發表于 10-22 21:56

    鴻蒙Flutter實戰:07混合開發

    參考資料 撰寫雙端平臺代碼(插件編寫實現鴻蒙Flutter功能開發 鴻蒙add-to-app示例 如何使用混合
    發表于 10-23 16:00

    鴻蒙生態-2022HDC鴻蒙應用與原子化服務全新技術呈現

    基礎的ArkTS語言介紹到高階分布式設備應用開發等一系列官方視頻課程,以及配套的開發文檔、SDK、API、示范代碼案例等。開發者通過學習本
    發表于 11-02 16:32

    全新升級的鴻蒙開發套件,你想知道的都在這里

    ArkTS應用一鍵上架分發,服務于HarmonyOS生態的全生命周期,開發完成后支持一鍵應用上傳發布到多終端。 本次華為還發布了可體驗鴻蒙
    發表于 11-04 18:47

    全新升級的鴻蒙開發套件,你想知道的都在這里

    、控件對象Dom樹、控件屬性等多項能力。AppGallery Connect 實現ArkTS應用一鍵上架分發,服務于HarmonyOS生態的全生命周期,
    發表于 11-07 17:22

    HarmonyOS/OpenHarmony應用開發-ArkTS的聲明式開發范式

    基于ArkTS的聲明式開發范式的方舟開發框架是一套開發極簡、高性能、設備應用的UI開發框架,支
    發表于 01-17 15:09

    鴻蒙 OS 應用開發初體驗

    的操作系統平臺和開發框架。HarmonyOS 的目標是實現設備的無縫協同和高性能。 DevEco Studio 對標 Android Studio,開發
    發表于 11-02 19:38

    CAPI SNAP開發及應用教程

    在之前的OpenPOWER歐洲峰會上,我們推出了全新的框架,旨在便于開發者開始采用CAPI加速其應用開發。CAPI存儲、網絡和分析編程框架,或者簡稱為
    發表于 11-16 13:16 ?2026次閱讀
    <b class='flag-5'>CAPI</b> SNAP<b class='flag-5'>開發</b>及應用教程

    鴻蒙開發ArkTS基礎知識

    更簡潔、更自然的方式開發應用。了解ArkTS之前,我們需要先了解下ArkTS、TypeScript和JavaScript之間的關系。 J
    的頭像 發表于 01-24 16:44 ?2683次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>開發</b>之<b class='flag-5'>ArkTS</b>基礎知識

    鴻蒙實踐-長列表解決方案和性能優化

    平臺都非常重要。HarmonyOS和iOS類似也提供了自己的解決方案。Roma(羅碼)作為端平臺,在此基礎上進行了具體的實踐。在實踐過程中,遇到了各種問題和挑戰,經歷了ArkTS+C
    的頭像 發表于 09-23 15:26 ?716次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>跨</b><b class='flag-5'>端</b><b class='flag-5'>實踐</b>-長列表解決方案和性能優化
    主站蜘蛛池模板: 欧美人成人亚洲专区中文字幕 | 中国二级毛片 | 午夜在线视频国产极品片 | 好男人资源免费观看1 | 日日噜噜大屁股熟妇 | 丰满的女朋友韩国版在线观看 | 热久久2018亚洲欧美 | 老少配xxxxx欧美 | 男人插曲视频大全免费网站 | 国产精品爽爽久久久久久蜜桃网站 | 日本漫画之无彩翼漫画 | 94色94色永久网站 | 嗯啊快拔出来我是你老师视频 | 一二三四在线播放免费观看中文版视频 | 成人国产亚洲欧美成人综合网 | 樱花草在线观看影院 | 久久久无码精品亚洲A片猫咪 | 国产亚洲精品久久综合阿香 | 国产精品久久久久久52AVAV | 免费韩伦影院在线观看 | 亚洲阿v天堂在线2017 | 99久久精品免费国产一区二区三区 | 日本三级按摩推拿按摩 | 青青青青草 | 在线精彩视频在线观看免费 | 明星三级电影 | 在线成人精品国产区免费 | 美女张开腿让男人桶爽无弹窗 | 日韩亚洲欧美中文高清 | 久久国内精品视频 | 久久91精品久久久久久水蜜桃 | 俄罗斯15一16处交 | 一本道高清码v京东热 | 超碰在线97av视频免费 | 日本护士hd | 东热rq大乱交 | 国语自产视频在线 | 午夜阳光影院在线观看视频 | 国产亚洲精品久久久久5区 国产亚洲精品久久久久 | 91精品在线国产 | 国产成人啪精视频精东传媒网站 |

    電子發燒友

    中國電子工程師最喜歡的網站

    • 2931785位工程師會員交流學習
    • 獲取您個性化的科技前沿技術信息
    • 參加活動獲取豐厚的禮品