Android 插件化开发:如何在插件中加载和使用 R 资源
在 Android 插件化架构中,主应用与插件(APK)共享同一个进程。通常情况下,res 目录下的每一个资源都会在 R.java 中生成一个对应的 Integer 类型的 ID。APP 启动时会把 R.java 注册到当前的上下文环境,我们在代码里以 R 文件的方式使用资源时正是通过使用这些 ID 访问 res 资源。
然而,插件的 R.java 并没有注册到当前的上下文环境,所以插件的 res 资源也就无法通过标准的 ID 方式直接使用了。
如何使用插件中的 R 资源
一种解决方式是插件里需要用到的新资源都通过纯 Java 代码的方式创建(包括 XML 布局、动画、点九图等),这种方式虽然有效但过于繁琐。
更通用的解决方案是修改 Context 的资源获取逻辑。记得我们平时怎么使用 res 资源的吗?就是调用 getResources().getXXX(resId)。让我们看看 getResources() 方法的实现链路。
1. 分析 Resources 获取链路
首先查看自定义或代理 Context 中的 getResources() 方法:
@Override
public Resources getResources() {
if (mResources != null) {
return mResources;
}
if (mOverrideConfiguration == null) {
mResources = super.getResources();
return mResources;
} else {
Context resc = createConfigurationContext(mOverrideConfiguration);
mResources = resc.getResources();
return mResources;
}
}
看起来是通过 mResources 实例获取资源。继续追踪 mResources 的初始化,发现它调用了父类 ContextThemeWrapper 里的 getResources() 方法:
Context mBase;
public ContextWrapper(Context base) {
mBase = base;
}
@Override
public Resources getResources() {
return mBase.getResources();
}


