hikage-runtime-attribute

Maven CentralMaven metadata URLAndroid Min SDK

这是 Hikage 的 XML 属性集合运行时模块,其提供了内存级别的 AAPT2 资源解析模拟器。

Play 合规风险提示

由于此模块涉及对 XmlBlock 的反射操作,可能存在与 Google Play 合规相关的风险。如果你的应用需要上架 Google Play,请务必仔细评估使用此模块可能带来的风险,并确保你的应用符合 Google Play 的政策要求。

Hikage 不为使用此模块可能引起的任何合规问题承担责任。

配置依赖

你可以使用如下方式将此模块添加到你的项目中。

我们推荐你优先参考 hikage-bom 使用 BOM 统一管理版本。

在你的项目 gradle/libs.versions.toml 中添加依赖。

[versions]
hikage-runtime-attribute = "<version>"

[libraries]
hikage-runtime-attribute = { module = "com.highcapable.hikage:hikage-runtime-attribute", version.ref = "hikage-runtime-attribute" }

在你的项目 build.gradle.kts 中配置依赖。

implementation(libs.hikage.runtime.attribute)

请将 <version> 修改为此文档顶部显示的版本。

传统方式

在你的项目 build.gradle.kts 中配置依赖。

implementation("com.highcapable.hikage:hikage-runtime-attribute:<version>")

请将 <version> 修改为此文档顶部显示的版本。

功能介绍

你可以 点击这里在新窗口中打开 查看 KDoc。

兼容性报告

以下是通过 Hikage 测试的系统版本列表和其对应的设备信息,以供参考。

Android 版本 / API 级别可用性测试设备
5.0.2 (21)Redmi Note 2
6.0 (23)OPPO A53
7.0 (24)Xiaomi Mi-4c
7.1.2 (25)Samsung Galaxy S4
8.0.0 (26)Xiaomi Mi-5s
Huawei P9
8.1.0 (27)SC801A
9 (28)Huawei P10 Plus
10 (29)Hisense A9
11 (30)OPPO A9
12 (31)Huawei nova 8
13 (33)Xiaomi MIX 2S
14 (34)ARM64 Emulator
15 (35)Redmi Note 12 Turbo
16 (36)Xiaomi 15 Ultra
17 (37)ARM64 Emulator

在 Hikage 中使用

通常情况下,此模块的能力将作为 hikage-core 的底座使用,你无需直接使用此模块的 API 来实现对 XML 属性集合的解析。

具体的使用方法请参考 hikage-core → XML 属性集合

在任意项目中使用

Hikage 对此模块提供了解耦的 API 能力,你可以开箱即用地在任何项目中使用此模块提供的 XML 属性集合解析能力。

AttributeSetResolver

我们为 TextView 创建一段 android:text 属性的 XML 资源,并将其解析为 AttributeSet 对象。

示例如下

// 假设这就是你的 Context 实例
val context: Context
// 创建 AttributeSet 解析器实例
val resolver = AttributeSetResolver.from(context)
// 返回一个 XmlResourceParser 对象,即 AttributeSet
val attrs = resolver.newParser(
    listOf(
        AttributeItem.from(
            name = "android:text", 
            value = AttributeItem.Value.Str("Hello dynamic attribute!")
        )
    )
)
// 创建 TextView,并传入解析后的 AttributeSet
val tv = TextView(context, attrs)

此时 tv 在装载到一个父布局或者在布局中被渲染时,就会被正确地设置上 android:text 属性,并显示 "Hello dynamic attribute!"。

AttributeSetResolver 支持传入 AttributeResolverParams 参数来配置其解析行为。

示例如下

// 假设这就是你的 Context 实例
val context: Context
// 假设这就是你需要构造的 AttributeItem 列表
val items: List<AttributeItem>
// 创建参数对象
val params = AttributeResolverParams(
    // 指定伪造的来源 XML 布局资源 ID,仅用于提供上下文信息,不会实际进行 inflate 操作
    sourceResId = R.layout.my_layout,
    // 指定解析的资源包名,而不是通过 Context 获取
    resourcePackageName = "com.example.myapp"
)
// 创建 AttributeSet 解析器实例
val resolver = AttributeSetResolver.from(context)
// 传入参数对象来解析 AttributeSet
val attrs = resolver.newParser(items, params)

你也可以更改 AttributeSetResolver 的全局默认参数,这将对整个项目中所有 AttributeSetResolver 的默认解析行为生效。

示例如下

AttributeSetResolver.defaultResolverParams = AttributeResolverParams(
    // ...
)

AttributeSetResolver 实现了 Closeable 接口,你可以在不需要使用它时调用 close() 方法来释放其占用的资源,或使用 use 来自动管理资源的释放。

示例如下

// 假设这就是你的 Context 实例
val context: Context
// 假设这就是你需要构造的 AttributeItem 列表
val items: List<AttributeItem>
// 创建 AttributeSet 解析器实例,并在 use 块中使用它
val attrs = AttributeSetResolver.from(context).use { resolver ->
    // 返回一个 XmlResourceParser 对象,即 AttributeSet
    resolver.newParser(items)
}
// 创建 TextView,并传入解析后的 AttributeSet
val tv = TextView(context, attrs)

AttributeSetResolver 还提供了一个 release(parser) 方法,其主要针对于 Android Studio 预览功能的 layoutlib,在实机运行中无需调用此方法。

AttributeItem

AttributeItem 是用于创建 AttributeSet 的数据类,你可以通过它来构造任意的 XML 属性集合。

AttributeItem.Value 提供了在构造过程中涉及到的四种类型:StrRawBoolReal

示例如下

val items = listOf(
    AttributeItem.from(
        name = "android:text", 
        // 最常用,直接传入字符串即可
        value = AttributeItem.Value.Str("This is a text")
    ),
    AttributeItem.from(
        name = "android:textSize", 
        // 字符串可被解析为最终的原始数值
        value = AttributeItem.Value.Str("16sp")
    ),
    AttributeItem.from(
        name = "android:padding", 
        // 字符串也可被解析为属性引用
        value = AttributeItem.Value.Str("?attr/actionBarSize")
    ),
    AttributeItem.from(
        name = "android:enabled", 
        // 只支持 true 或 false
        value = AttributeItem.Value.Bool(true)
    ),
    AttributeItem.from(
        name = "android:alpha",
        // 对应 XML 中的 float 格式,例如 1.0 或 0.5
        value = AttributeItem.Value.Real(0.5f)
    ),
    AttributeItem.from(
        name = "android:layout_weight", 
        // 原始数值或 ID、Enum 等类型的属性值
        value = AttributeItem.Value.Raw(1)
    )
)

如果你拿不准什么场景用什么,直接选 AttributeItem.Value.Str 就对了,XML 里面有什么,它就支持什么。

当然你也可以给定 namespace 来指定属性的命名空间而不是每次都需要使用 : 来指定。

示例如下

val item = AttributeItem.from(
    namespace = "android",
    name = "text", 
    value = AttributeItem.Value.Str("This is a text")
)

AttributeItem 实现了 Serializable 接口,你可以将其序列化为任意对象例如 JSON 进行传输,并在需要时反序列化回对象。