插件化技术-提取公共库插件

上节我们创建了一个应用插件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-with-lib

【进阶】以下将帮助你理解公共库资源的实现原理。 重新检查 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 的本质原因。

猜你喜欢

转载自blog.csdn.net/LUFANZHENG/article/details/77160813