-->

How the flavor-specific variants are working?

2019-09-08 03:41发布

问题:

If you need flavor you should go to build gradle and add the flavors that you need

Like this

productFlavors {
mock {
  applicationIdSuffix = ".mock"
}
prod {}
}

and then you need to create corresponding dir like this /src/prod/java/

How I thought it should work, according to build variant that was choosen for example prodDebug androidStudio will take as a base main source and substitute coresponding classes from dir according to choosen build variant.

But then I found this snippet which said next

Files in the flavor-specific folders do not replace files in the main source set. Trying to do that will result in a duplicate class exception. This is a common misconception because it's how resources are merged.

回答1:

Ok, so with basic configuration with flavors, you have two kinds of source sets:

  1. main source set
  2. flavor-specific source sets, like your mock and prod

With standard buildTypes configuration (debug and release), this gives you the following build variants (combinations of build types and product flavors):

  1. mockDebug
  2. mockRelease
  3. prodDebug
  4. prodRelease

Each one of them uses every source set that corresponds with flavor/type name and the main set, so for example, the prodRelease will use all of the following source sets at once:

  1. /src/main
  2. /src/prod
  3. /src/release

Effectively, the build system will 'merge' all of these into one source set, and that means if there are classes with the same path and name in these sets, a name clash occurs and compiler will fail.

The way to use source sets correctly is to omit the class that you need to be different for each set from the main set, but instead provide it with all the sets for each flavor / each buildType, for example:

  1. main set has class A.java that references class B.java. B.java is omitted from main set.
  2. Different B.java files are included in mock and prod sets (of course, don't need to be different, but need to provide the same interface, preferably with interface included in main set).
  3. Compiler uses B.java from the set that is being used by the current configuration - build variant, so either the mock or the prod one.
  4. Yay! Now you have two functionally different product flavors.

This behavior doesn't limit to classes, you can use flavor or type specific resources, AndroidManifest.xml files and just about anything that goes into the source dir.

Tip: In Android Studio you can see in the 'project files' section which files will be chosen to compile for a specific variant. To switch build variants, hit Cmd+Shift+A (mac keymap) and search for Build Variants phrase. It usually shows also on the left bottom side of the Android Studio window.



回答2:

The code from the main source set will always make it into the APK. The source files in other source sets will only be merged if the correct build variant is used. For example, you can create two files:

  • src/mock/java/yourpackage/MyClass.java
  • src/prod/java/yourpackage/MyClass.java

Depending on whether you're building prod or mock variant, one of those classes will be compiled and packaged with the APK. Same works for debug and release: you can have code and resources that are only packaged into debug or release versions of the app.