Mobile Development 28 min read

How Dynamic Cross‑Platform UI Rendering Works on HarmonyOS, Android, iOS, and Web

This article explains the architecture and implementation of the Roma dynamic cross‑platform solution, covering its JavaScript‑VM based rendering pipeline, HarmonyOS integration challenges, resource packaging, view creation across JS, C++, and ArkTS layers, and the diff‑based update mechanism that enables seamless UI updates on multiple platforms.

JD Cloud Developers
JD Cloud Developers
JD Cloud Developers
How Dynamic Cross‑Platform UI Rendering Works on HarmonyOS, Android, iOS, and Web

1. Introduction

Through this article you will gain a clear understanding of the implementation principles of dynamic cross‑platform rendering, following the journey of the Roma engine from code packaging to native view drawing.

2. Principle Overview

2.1 Dynamic Cross‑Platform Principle

Dynamic‑Roma is a self‑developed one‑stop cross‑platform solution that runs the same code on Android, iOS, HarmonyOS and Web. Its principle is similar to React Native and Weex: each platform provides a JavaScript virtual machine that loads bundled JS, parses it into instructions, and invokes native host capabilities to transfer data and render views.

Special considerations for HarmonyOS include the ArkTS language and the ArkVM which only loads compiled abc files, requiring a V8 port and a JSVM‑API provided by Huawei.

Can the ArkVM load JS files directly?

Can the JS VM efficiently execute dynamic instructions?

How to integrate the SDK on HarmonyOS?

Roma provides a static library libRomaSdk.so that can be linked via CMake/Ninja; after adding the dependency the dynamic capabilities are available.

2.2 HarmonyOS Integration

At app start the SDK loads a JS Engine and a Jue Instance, initializing the runtime, managing instances, virtual DOM, layout and event handling.

A unified external interface (JS Engine Interface) defines instance creation, lifecycle, element CRUD, bidirectional communication and hot‑reload, allowing each platform to implement the same contract.

In the JS Engine environment a V‑Dom Tree is built, then the native side creates a Render Tree based on it, which is finally laid out and displayed.

3. Business Example

A simple dynamic page in JD Finance demonstrates loading, updating an image and changing a div background color.

3.1 Business Code

The page is written in a Vue‑like language Jue (template, script, style).

<template style="border-width: 2px;">
  <div class="normalClass" style="margin-top: 100px;">
    <image class="normalClass" :src="imageUrl" style="height: 200;"></image>
    <div class="normalClass" :style="{'background-color':bgColor}" style="height:60px;">
      <text style="border-width: 2px;width:260px;height:40px;align-self: center;text-align: center;background-color: white;" @click="change()">更新节点数据</text>
    </div>
  </div>
</template>
<script>
export default {
  data() { return { bgColor: "white", imageUrl: "https://static.foodtalks.cn/company/images/434/121logo.png" } },
  methods: { change() { this.bgColor = "red"; this.imageUrl = "https://www.szniego.com/uploads/image/20210202/1612232326.png"; this.updateInstance(); } }
}
</script>
<style scoped>
.normalClass { margin: 10px; justify-content: center; align-items: center; align-self: stretch; border-width: 2px; }
</style>

3.2 Resource Loading Process

The ADemo.jue file is packaged into ADemo.zip, delivered to the client, unpacked, decrypted and the resulting ADemo.js is loaded by the JS VM to start view rendering.

3.3 Product Code

Key parts of ADemo.js are shown, illustrating how templates are transformed into node creation calls.

/******/ (function(modules) { })
/******/ ({
/***/ "./src/jueDemoList/ADemo/ADemo.jue":
/*!*******************************************!\
  !*** ./src/jueDemoList/ADemo/ADemo.jue ***!
  \*******************************************/
/*! exports provided: default */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
var template = JRTemplateManager._jr_create_jue_template('ADemo.jue', {"id":"ADemo","version":"11","dependencies":{"JSEngine":"0.9.4"}});
JRTemplateManager._jr_create_t_node('ADemo.jue','0','40e129af-5e6a-70b8-a757-28a22785dc2f','document',{"style":"border-width: 2px;"});
... (additional generated node creation code) ...
});
//# sourceMappingURL=ADemo.js.map

4. View Rendering Process

4.1 Rendering Principle

After the resource is loaded, the native side creates an Instance via N‑API, which calls the JS Engine to build the V‑Dom Tree, passes it to C++ to construct a Component Tree, and finally the Render Tree is built in ArkTS and displayed.

The three language environments (JS, C++, ArkTS) each maintain an independent Instance that correspond to UI, data, and event threads.

4.2 Code Analysis

Key native methods such as aboutToAppear , createInstance , startInstance , and the JSI bridges are examined, showing how instances are created in each environment and how mutations are propagated.

public void aboutToAppear() {
    romaAssetsManager.ensureAsset(this.jueName, progress).then(version => {
        this.romaInstance = this.createInstance(this.rootContent, this.pageId);
        this.romaInstance!.startInstance(this.initialProps).then(result => {});
    }).catch(error => {});
}

private RomaInstance createInstance(NodeContent root, String pageId) {
    return RomaEnv.createAndRegisterRomaInstance(this.jueName, new RomaInstanceParam(root, getUIContext(), getContext(this), pageId, errorListener), this.stateListener);
}

public async startInstance(TObject initialProps) {
    return this.napiBridge.startInstance(this.getId(), initialProps);
}

4.3 Rendering in ArkTS

The RomaComponentFactory builds concrete components (document, div, text, image) based on the descriptor generated from the Render Tree.

@Builder
function RomaComponentFactoryBuilder(param) {
  if (param.type == "document") { RomaDocument({componentCtx: param.componentCtx}); }
  else if (param.type == "div") { RomaDiv({componentCtx: param.componentCtx}); }
  else if (param.type === "text") { RomaText({componentCtx: param.componentCtx}); }
  else if (param.type === "image" || param.type === "img") { RomaImageView({componentCtx: param.componentCtx}); }
  else { RomaCustomComponentFactory.customComponentBuilder.builder(param.componentCtx); }
}

5. View Update Process

When the “Update node data” button is pressed, the image URL and div background are changed. The update follows the same three‑instance pipeline, using a diff algorithm to compare the new V‑Dom Tree with the old one and apply only the changed nodes.

5.1 Diff Principle

A new V‑Dom Tree is generated, diffed against the previous tree, and the resulting mutation list updates the Render Tree.

6. Planning Summary

Three threads ensure efficient processing across environments, but the current ArkUI component hierarchy adds overhead. Future work will integrate Huawei’s C‑API to render directly in C++, reducing component depth and cross‑language communication cost.

Dynamic Roma spans Android, iOS, HarmonyOS, Web, Java, C/C++, Vue, JavaScript, Node, Webpack, Clang, Ninja, and invites further discussion.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Mobile DevelopmentSDKJavaScriptui-renderingHarmonyOS
JD Cloud Developers
Written by

JD Cloud Developers

JD Cloud Developers (Developer of JD Technology) is a JD Technology Group platform offering technical sharing and communication for AI, cloud computing, IoT and related developers. It publishes JD product technical information, industry content, and tech event news. Embrace technology and partner with developers to envision the future.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.