Android Source Set 与 Build Varia
今天看android mvp官方源码,遇到一个很奇葩的问题,在main目录下面的一个类,TasksActivity引用到了一个Injection类,如图:
引用代码而这个类不在main目录下面,在mock变体的源码路径下:
实现代码然后app的gradle脚本并没有设置sourceSet属性:
defaultConfig设置只定义了两个Flavor:
Flavor定义.png所以我百思不得其解,它是怎么找到其他变体的源码的。所以各种问人,各种查资料,各种做实验,一度怀疑是android gradle插件默认支持把mock变体的源码,也作为默认版本的源码路径(现在想起来比较搞笑),直到最后看到这篇博客。
了解之后才发现,实际上,它之所以能应用mock变体下面的代码,是因为我们构建的就是mock变体,可以在AndroidStudio左下方的BuildVariants模块查看。每个变体都有默认与它同名(vraint = "flavor" + "buildtype")的特有的资源目录,可以用gradle的sourceSets任务打印出来,但是同时每个变体都会依赖main模块的代码。
那这样就有个问题,main目录依赖了某一个变体的代码,在构建另一个变体的时候,如果没有这个代码不是会编译失败吗?理论上是的,所以要依赖变体特有的代码,必须在其他变体里也实现相同包名、类名、方法的类才行。我们可以看到在prod变体下面也有一个相同的Injection类:
prod变体下的实现这种方法真的是让人大跌眼镜。。。。
这么简单的原因,我们一直想不到,主要是因为我们没有弄清楚main和变体资源目录的依赖关系,平时我们构建的debug和release版本,也有自己的特殊资源目录,但是我们一般都不会使用。虽然我也编写过测试代码,但是都是正向依赖,构建的时候都是直接运行或者执行任务,从来没有想过变体的资源引用问题,一旦看到一个反向的依赖,就一脸懵逼。
好了,以上就是答案。有时候遇到问题,反而是加深我们对某些方面认识的契机,一定要追根究底。解决之后就像打通了任督二脉一样,功力爆增,心情还极爽,哈哈。