GaiaX Documentation

repository·main·Indexed 23 days ago

https://github.com/alibaba/gaiax

A lightweight, pure-native dynamic card cross-platform solution developed by Alibaba's Youku team. GaiaX enables low-code development by allowing the creation and rendering of dynamic UI components (cards) across Android, iOS, and HarmonyOS using native rendering engines.

Tokens
60.5K
Snippets
161
Records
276
Agent score
80%

What's inside GaiaX

  1. Overview of GaiaX Cross-Platform Dynamic Card Solution

    main

    GaiaX is a lightweight, cross-platform, pure-native dynamic card solution developed by Alibaba's Youku technical team. It enables low-code development for clients while maintaining native performance and experience.

    GaiaX provides:

    • Client SDKs: Native implementations for Android, iOS, and HarmonyOS.
    • Studio: A visual template building tool.
    • Demo Projects: For testing and previewing templates.

    The full lifecycle supported includes template creation, editing, real-device debugging, and previewing.

  2. Overview of HarmonyOS JSVM-API

    main

    HarmonyOS JSVM-API is a C-language interface (following the C99 standard) that provides a stable set of APIs based on a standard JS engine. It allows developers to manage the lifecycle of the JS engine, execute dynamic JS code, and facilitate high-performance interaction between JavaScript and C/C++.

    Key Capabilities:

    • Engine Management: Create and destroy JS engines.
    • Code Execution: Execute dynamically loaded JS code during application runtime.
    • JS/C++ Interop: Implement performance-critical core functions in C/C++ and register them as methods in the JS environment for direct calling from JS code.
  3. What is Nimble?

    main

    Nimble is a matcher framework used to express the expected outcomes of Swift or Objective-C expressions. It provides a more natural and readable syntax for assertions compared to standard XCTest macros, and it simplifies writing asynchronous tests.

    // Swift
    expect(1 + 1).to(equal(2))
    expect(1.2).to(beCloseTo(1.1, within: 0.1))
    expect(3) > 2
    expect("seahorse").to(contain("sea"))
    expect(["Atlantic", "Pacific"]).toNot(contain("Mississippi"))
    expect(ocean.isClean).toEventually(beTruthy())
  4. Compare GaiaX Android and Harmony SDK capabilities

    main

    This document provides a detailed comparison between the GaiaX Android SDK and the GaiaX Harmony SDK across several core dimensions. Use this to understand the current feature parity and identify missing capabilities in the Harmony implementation.

    Core Engine Comparison

    • Template Engine: Android has full support for multi-level caching, template hot updates, and multi-version management. Harmony has basic support with LRU caching and lacks hot updates and version management.
    • Registration Center: Android supports a wide range of extension interfaces (Expressions, Data Binding, Color, Size, Dynamic Properties) and custom view registration. Harmony currently only supports basic template source registration.

    Template System Comparison

    • Basic Components: Android supports Lottie, Custom components, Progress bars, and IconFonts. Harmony currently lacks these.
    • Container Components: Android supports advanced features like item-footer-type and hasMore for pagination in Grid/Scroll containers. Harmony lacks these mechanisms.

    Style System Comparison

    • Style Attributes: Android supports advanced properties like hidden, complex border-style (dashed, single-sided), and rich mode/mode-type for image cropping. Harmony's support is more simplified, focusing on basic width, height, margin, padding, and color.
    • Shadows & Filters: Android supports full box-shadow parameters and backdrop-filter. Harmony uses a simplified fixed-string approach for shadows and lacks full support for background filters (though backgroundBlurStyle can be used via ArkTS).
  5. GaiaX Harmony SDK Capabilities and Limitations

    main

    The GaiaX SDK for Harmony is designed to align with the Android implementation by reusing core C++/Rust engines (Stretch for layout and GXAnalyze for expressions).

    Supported Core Features

    • Template Loading: Supports loading templates from assets and rawfile.
    • Layout Engine: Uses the same Stretch(Rust) .so as Android, ensuring FlexBox layout parity.
    • Expression Engine: Uses GXAnalyze(C++) .so for consistent logic.
    • Basic Components: View, Text, Image, and RichText are fully supported.
    • Container Components: Scroll, Grid, and Slider have basic support.
    • Styling: Supports width/height, margin/padding, color, font, opacity, line height, gradients, shadows, and border-radius.

    Current Limitations (Requires Alignment)

    • Template Management: Lacks template hot-updates, multi-version management, and advanced multi-level caching (currently uses GXTemplateLRUCache).
    • Component Gaps: Missing Lottie animations, Progress bars, IconFont, and custom component registration (registerExtensionViewSupport).
    • Container Gaps: Scroll, Grid, and Slider lack Header and Footer support (including 'load more' functionality).
    • Styling Gaps: hidden attribute is not yet active (relies on display/overflow), border-style (e.g., dashed) is unsupported, and advanced image cropping modes are limited.
  6. How Nodes and Layouts work together

    main

    Stretch uses a tree structure of Node objects to represent a layout.

    • Nodes: The core building blocks. Each Node requires a Style (describing flexbox properties). Nodes can have children to form a tree.
    • Layouts: When you call computeLayout, Stretch produces a tree of Layout nodes. This tree mirrors the structure of your Node tree but contains the actual computed position and size information.
    • Recomputation: Nodes can be mutated (e.g., via setStyle). Stretch automatically recomputes only the subtrees that have changed, making it efficient for large trees where only specific elements change.
    import UIKit
    import StretchKit
      
    class ViewController: UIViewController {
      
      override func viewDidLoad() {
        let node = Node(
          style: Style(), 
          children: [
            Node(style: Style(size: Size(width: .percent(0.5), height: .percent(0.5))), children: [])
          ]
        )
        
        let layout = node.computeLayout(thatFits: Size(width: nil, height: nil))
        layout.width; // 100.0
        layout.height; // 100.0
        layout.children.count; // 1
      }
    }
  7. How Nodes and Layouts work in Stretch

    main

    Stretch uses a tree-based layout system:

    1. Nodes: The core building blocks. Each Node requires a Style describing its flexbox properties. Nodes can be arranged in a parent-child hierarchy to form a tree.
    2. Layout Tree: When you call compute_layout, Stretch generates a tree of Layout nodes. This tree mirrors the structure of your Node tree but contains the actual computed dimensions (width, height, etc.) for each element.
    3. Incremental Recomputation: Stretch is optimized for performance. When you mutate a node (e.g., via set_style), Stretch automatically recomputes only the subtrees that have changed, making it efficient for large UI trees.
    use stretch::{style::*, node::{Node, Stretch}, geometry::Size};
     
    fn main() {
      let stretch = Stretch::new();
      
      let node = stretch.new_node(Style { ..Default::default() }, vec![
        stretch.new_node(Style {
          size: Size {
              width: Dimension::Points(100.0),
              height: Dimension::Points(100.0),
          },
          ..Default::default()
        }).unwrap()
      ]).unwrap();
      
      stretch.compute_layout(node, Size::undefined()).unwrap();
      let layout = stretch.layout(node).unwrap();
      
      layout.width; // 100.0
      layout.height; // 100.0
    }
  8. Test for exceptions and lazily computed values

    main

    Nimble's expect function evaluates the expression lazily, allowing it to catch exceptions raised during evaluation.

    Swift Note: Swift does not have native exceptions; Nimble can only catch exceptions raised by Objective-C code.

    Objective-C Note: When making an expectation on an expression that has no return value, you must use the expectAction macro.

  9. Implement Property Interception Callbacks

    main

    JSVM allows you to intercept property operations on objects by providing callback functions. This is useful for implementing custom object behavior in C/C++ that is triggered by JavaScript property access.

    // Example: Intercepting property GET requests
    static JSVM_Value GetPropertyCbInfo(JSVM_Env env, JSVM_Value name, JSVM_Value thisArg, JSVM_Value data) {
        char strValue[100];
        size_t size = 0;
        // Get the name of the property being accessed
        OH_JSVM_GetValueStringUtf8(env, name, strValue, 300, &size);
        
        JSVM_Value newResult = nullptr;
        char newStr[] = "new return value hahaha from name listening";
        OH_JSVM_CreateStringUtf8(env, newStr, strlen(newStr), &newResult);
        
        return newResult;
    }
  10. Set aspect ratio for media content

    main

    The aspectRatio property allows you to enforce a specific ratio between width and height (e.g., a value of 2 means width is twice the height).

    • Accepts any float $> 0$.
    • Respects minSize and maxSize.
    • Has higher priority than flexGrow.
    • If aspectRatio, width, and height are all set, the cross axis dimension is overridden.
    • Default: null (no aspect ratio enforced).
  11. GaiaX Harmony JS Runtime Architecture

    main

    The GaiaX JS Runtime for Harmony aims to reconstruct the Android runtime environment using the JSVM-API. The goal is to allow GaiaX templates to run identical JavaScript logic across both platforms.

    Core Runtime Components

    • JSVM Engine Layer: Wraps JSVM lifecycle (VM/Env creation, destruction, and Scope management). It provides an evaluate(script, filename, mode) capability.
    • GaiaXJSBridge: Injected via JSVM_CallbackStruct to enable bidirectional JS $\leftrightarrow$ Native communication. It supports:
      • bridge.callSync
      • bridge.callAsync
      • bridge.callPromise
    • Timer & Microtasks: Implements setTimeout, setInterval, clearTimeout, and clearInterval using the JSVM to ensure Promise and asynchronous chains function correctly.
    • Bootstrap: Reuses the Android bootstrap.js and module source code to provide a consistent JS world (including Page, Component, EventTarget, window, etc.).
    • ArkTS Host Integration: Intercepts native events (click, long press, scroll, exposure) in ArkTS components, encapsulates them as JSON, and sends them to the JSVM via NAPI.