上节我们创建了一个应用插件app.main,这个插件存在以下资源:
app.main/src/main/res
├── values
│ ├── colors.xml
│ ├── dimens.xml
│ └── styles.xml
└── values-w820dp
└── dimens.xml
这些资源定义了该应用的主题、界面边距等样式,在多个应用插件间,这些资源应该是 可被复用 的。
这个时候,我们可以通过提取公共库插件模块来解决这些问题。
【进阶】为了便于理解一些细节,我们可以先通过命令:
aapt dump --values resources app/smallLibs/x86/libcom_example_appmain.so来观察下 app.main 插件的资源情况:
resource 0x77040000 com.example.appmain:style/AppTheme: <bag> Parent=0x7f080103(Resolved=0x7f080103), Count=3可以看到,AppTheme的ID是 0x77 打头的插件资源, 同时它的 Parent 指向了 0x7f 打头的资源,即宿主资源。
创建公共库插件模块
右键 app
模块 > New > Module,创建一个 Android Library
模块。 Application/Library name
设置为 Lib.style
,其它项目将默认为:
- Module name: lib.style
- Package name: com.example.libstyle
将 app.main/src/main/res/values 下除了 strings.xml 的文件移动到 lib.style/src/main/res/values 目录下; 将 app.main/src/main/res/values-w820dp 整个目录移动到 lib.style/src/main/res/ 目录下。
为了确认公共库提取成功,我们修改 lib.style/src/main/res/colors.xml,将主色调改为绿色:
<color name="colorPrimary">#2FA739</color>
添加公共库引用
修改 app.main/build.gradle,增加对 lib.style 的依赖:
dependencies {
...
compile project(':lib.style')
}
添加插件路由
修改 app/assets/bundle.json:
{
"pkg": "com.example.libstyle"
}
重新编译插件
清除公共库:
./gradlew cleanLib -q
window命令:
gradlew cleanLib -q
编译公共库:
./gradlew buildLib -q -Dbundle.arch=x86
window命令:
gradlew buildLib -q -Dbundle.arch=x86//这个命令上一小节已经介绍过了不再重复
编译业务单元:
./gradlew buildBundle -q -Dbundle.arch=x86
window命令:
gradlew buildBundle -q//如果不是安装到模拟器不需编译到x86
重新运行程序
菜单栏上选择 app 模块,运行,将看到绿色的ActionBar:
【进阶】以下将帮助你理解公共库资源的实现原理。 重新检查 app.main 的资源情况:
aapt dump --values resources app/smallLibs/x86/libcom_example_appmain.so将输出:
Package Groups (1) Package Group 0 id=0x77 packageCount=1 name=com.example.appmain DynamicRefTable entryCount=1: 0x77 -> com.example.appmain Package 0 id=0x77 name=com.example.appmain type 1 configCount=1 entryCount=1 spec resource 0x77020000 com.example.appmain:layout/activity_main: flags=0x00000000 config (default): resource 0x77020000 com.example.appmain:layout/activity_main: t=0x03 d=0x00000000 (s=0x0008 r=0x00) (string8) "res/layout/activity_main.xml"可以看到,关于主题、边距等资源已经被剥离了。 具体是如何引用到公共库的资源呢,我们来看下 app.main/AndroidManifest.xml 的内容:
aapt dump --values xmltree app/smallLibs/x86/libcom_example_appmain.so AndroidManifest.xml重点关注主题的部分:
E: application (line=11) A: android:theme(0x01010000)=@0x79030000可以看到主题指向了 0x79,我们来确认下这个资源是属于 lib.style 插件的:
aapt dump --values resources app/smallLibs/x86/libcom_example_libstyle.so关注 0x79030000 这个资源项目:
spec resource 0x79030000 com.example.libstyle:style/AppTheme: flags=0x00000000 config (default): resource 0x79030000 com.example.libstyle:style/AppTheme: <bag> Parent=0x7f080103(Resolved=0x7f080103), Count=3确实是 AppTheme 主题,同时该主题的 Parent 指向了宿主资源 0x7f080103。 正是由于 Small 完成了这个资源链路,从而保证系统在合并这些插件的时候可以正确的追溯到主题资源。 你可以进一步 dump 宿主包查看该资源的定义,该资源就是 AppCompat 包所带的资源,这也是之所以 Small 能支持 AppCompat 的本质原因。