hikage-runtime-attribute
这是 Hikage 的 XML 属性集合运行时模块,其提供了内存级别的 AAPT2 资源解析模拟器。
Play 合规风险提示
由于此模块涉及对 XmlBlock 的反射操作,可能存在与 Google Play 合规相关的风险。如果你的应用需要上架 Google Play,请务必仔细评估使用此模块可能带来的风险,并确保你的应用符合 Google Play 的政策要求。
Hikage 不为使用此模块可能引起的任何合规问题承担责任。
配置依赖
你可以使用如下方式将此模块添加到你的项目中。
我们推荐你优先参考 hikage-bom 使用 BOM 统一管理版本。
Version Catalog (推荐)
在你的项目 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 提供了在构造过程中涉及到的四种类型:Str、Raw、Bool 和 Real。
示例如下
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 进行传输,并在需要时反序列化回对象。