建立及自訂元件目錄

在 A2UI 架構中,每個介面都是由元件目錄驅動。 目錄是正式合約,定義 AI 代理程式可用的 UI 元件、屬性結構定義和本機用戶端函式。代理程式必須使用目錄中宣告的元件建構使用者介面,而不是產生任意程式碼或發明不明元素。

換句話說,目錄會宣告元件,而代理程式會使用這些元件建構應用程式的 UI。

使用 Jetpack Compose A2UI 算繪器建構 Android 應用程式時,您可以彈性選擇提供目錄的方式:

  • 基本目錄:A2UI 專案定義了名為「基本目錄」的標準化通用規格,其中包含按鈕、文字、文字欄位、資訊卡和清單等常見元素。AndroidX 程式庫 androidx.compose.material3:material3-a2ui 使用原生 Material Design 3 元件,提供這項基本目錄規格的現成實作方式。androidx.a2ui.compose:compose-ui 程式庫也提供基本目錄的通用結構定義,有助於為自己的設計系統實作基本目錄。
  • 自訂目錄:對於有自己獨特設計系統的正式版應用程式,您可以從頭開始建構自訂目錄。這會將代理程式限制在應用程式的確切元件、樣式權杖和視覺語言。
  • 子集或混合:您可以將提供的基本目錄中的特定元件實作項目,與自己的自訂元件合併,或覆寫基本目錄套件中的個別元件實作項目。

使用隨附的基本目錄

如要快速開始使用,不必從頭編寫元件結構定義,可以改用A2UI 基本目錄規格的實作項目。androidx.compose.material3:material3-a2ui 程式庫會使用 Material Design 3 元件實作基本目錄。

例項化 materialA2uiBasicCatalogV1 時,請提供下列項目的算繪器和處理常式:

  • 媒體元件,例如圖片、影片和音訊播放器
  • 網址開啟器
  • 在地化訊息格式

A2UI 程式庫刻意不綁定外部媒體和網路依附元件,例如 Coil、Glide 或 Media3。而是提供自己的算繪器。藉由提供專屬程式庫,避免依附元件衝突。舉例來說,如果應用程式已使用 Coil 載入圖片或使用 Media3 播放內容,可以直接將這些現有程式庫插入目錄。

以下範例說明如何例項化 Basic Catalog,以及連結偏好的媒體程式庫、網址開啟器和訊息格式化工具:

// Instantiate the provided Basic Catalog (implemented with Material 3)
val basicCatalog = materialA2uiBasicCatalogV1(
    // Example: Wire up Coil for image loading (via AsyncImage)
    image = MaterialA2uiBasicCatalogV1Defaults.image {
            url, description, scale, modifier, onError ->
        AsyncImage(
            model = url,
            contentDescription = description,
            contentScale = scale,
            modifier = modifier,
            onError = { state -> onError(state.result.throwable) },
        )
    },

    // Example: Use ExoPlayer/Media3 for video
    video = MaterialA2uiBasicCatalogV1Defaults.video { url, modifier, onError ->
        // Custom ExoPlayer video integration here
    },

    // Example: Use an audio player
    audioPlayer = MaterialA2uiBasicCatalogV1Defaults.audioPlayer {
            url, description, modifier, onError ->
        // Custom audio integration here
    },

    // Handle outbound URLs, such as using an app navigator or context intents.
    urlOpener = { url ->
        appNavigator.openUrl(url)
    },

    // Handle localized message formatting
    messageFormatter = { pattern, locale, args ->
        MessageFormat.format(context, locale, pattern, args)
    },
    localeProvider = A2uiLocaleProvider.Default,
)

從頭開始組裝自訂元件目錄

如果應用程式使用自訂設計系統,您可以定義自己的目錄,其中包含自訂 A2uiComponent 實作項目。這個方法可讓您全面掌控向代理程式公開的元件結構定義,以及發出的原生 Compose UI:

// Define a custom catalog that mirrors your app's design system
val CustomDesignSystemCatalog = A2uiCatalog(
    catalogId = "https://example.com/catalogs/my-design-system/v1/catalog.json",
    components = listOf(
        CustomButtonComponent,
        CustomCardComponent,
        CustomTextFieldComponent,
    ),
    functions = listOf(MyCustomLocalFunction()),
)

如需定義個別元件結構定義及其 Compose UI 算繪邏輯的相關操作說明,請參閱「實作自訂 A2UI 元件」。

搭配自訂元件使用基本目錄元件的子集

您不必嚴格選擇從頭開始建構所有內容,或是採用整個基本目錄。您可以組合目錄,將提供的基本目錄實作中的選取元件,與您自己的自訂元件合併:

// Assemble a catalog using select Basic Catalog components alongside custom components
val hybridCatalog = A2uiCatalog(
    catalogId = "https://example.com/catalogs/my-app/v1/catalog.json",
    components = listOf(
        // Use provided Basic Catalog components (built with Material 3)
        MaterialA2uiBasicCatalogV1Defaults.text,
        MaterialA2uiBasicCatalogV1Defaults.card,

        // Add proprietary components from your app's design system
        CustomChartComponent,
        CustomProductCardComponent,
    ),
    functions = createBasicCatalogFunctions(...),
)

或者,您也可以覆寫特定元件位置,自訂提供的 Basic Catalog 套件:

// Override specific components within the Basic Catalog suite
val customizedBasicCatalog = materialA2uiBasicCatalogV1(
    // Supply required renderers (such as Coil or ExoPlayer) as shown earlier
    image = MaterialA2uiBasicCatalogV1Defaults.image(myImageRenderer),
    video = MaterialA2uiBasicCatalogV1Defaults.video(myVideoRenderer),
    audioPlayer = MaterialA2uiBasicCatalogV1Defaults
        .audioPlayer(myAudioRenderer),
    urlOpener = { url -> /* Open URL */ },
    messageFormatter = { pattern, _, _ -> pattern },
    localeProvider = A2uiLocaleProvider.Default,
    // Replaces the default button. If you use this, implement the
    // A2uiBasicCatalogV1.Button interface.
    button = MyCustomBrandButtonComponent,
    
)

管理目錄版本和結構定義演進

A2UI 目錄會根據 JSON 結構定義合約明確設定版本。導入破壞性結構定義變更時,必須調升版本:

// Original component (v1 catalog)
object CustomButtonComponent : A2uiComponent { ... }

// Unchanged component across versions
object CustomTextComponent : A2uiComponent { ... }

// Future breaking schema change (v2 catalog)
object CustomButtonComponentV2 : A2uiComponent { ... }

// Assembles the v1 catalog
fun customCatalogV1(
    button: A2uiComponent = CustomButtonComponent,
    text: A2uiComponent = CustomTextComponent,
): A2uiCatalog = A2uiCatalog(
    catalogId = "https://example.com/catalogs/my-app/v1/catalog.json",
    components = listOf(button, text),
)

// Assembles the v2 catalog
fun customCatalogV2(
    button: A2uiComponent = CustomButtonComponentV2,
    text: A2uiComponent = CustomTextComponent,
): A2uiCatalog = A2uiCatalog(
    catalogId = "https://example.com/catalogs/my-app/v2/catalog.json",
    components = listOf(button, text),
)

如要啟用無停機時間的無縫遷移,用戶端可以同時向訊息處理器註冊多個支援的目錄版本:

private val processor = A2uiMessageProcessor(
    catalogs = listOf(
        customCatalogV1(),
        customCatalogV2(),
    ),
)

目錄協商期間,代理程式會探索所有支援的目錄 ID,並針對每個平台指定適當版本。

實作詳細資料

以下各節說明內部目錄驗證和結構定義協商。

目錄管理使用者歷程會介紹下列重要 API:

  • A2uiCatalog:用於定義元件目錄的介面和頂層工廠函式。
  • materialA2uiBasicCatalogVX:版本化工廠函式 (例如 materialA2uiBasicCatalogV1),提供標準 A2UI Basic Catalog 規格的 Material 3 實作項目。
  • A2uiReadinessEvaluatorasReadinessEvaluator()A2uiReadinessEvaluator 是評估元件準備程度的介面。asReadinessEvaluator() 擴充功能函式會使用目錄中註冊的元件,解析準備狀態。

A2UI 版本目錄和元件結構定義

目錄結構定義與特定通訊協定版本相關聯。 通訊協定演進時,目錄定義會更新版本。這個新版本的元件實作項目可以使用更新的算繪器 API,而較舊的版本仍可並行運作。