We know that Android projects automatically generate an R.java class to hold the identity of all resource files in the project. The resource declaration in R.Java generated in the main project is a static constant, whereas in Module it is a static variable. Why is that? We know that in Java, if a value is declared as a constant (decorated with final), it is directly replaced with a value after compilation. In Java syntax, attributes in annotations and case expressions in switch-Case must use constants or direct values, otherwise a syntax error will be reported. Next, we will discuss why the resource identifier declared in the MODULE R class is not final, and what causes this phenomenon?
In the main project
For example, if you create an activity_main. XML layout file in your main project, r.java will automatically include the following static constants in a line.
public static final class layout {
...
public static final int activity_main=0x7f09001b;
Copy the code
You can then use the resource as r.layout.activity_main
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); }}Copy the code
When we compile the above code to get mainActif. class, we find that the static constants are directly replaced with values. As the code runs, you can find the corresponding resource directly from the value.
public class MainActivity extends AppCompatActivity {
public MainActivity() { } protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.setContentView(2131296283); }}Copy the code
In the Module
Then we create a MainActivity and its corresponding resource in a module. We look at R.Java in that module.
public static final class layout {
...
public static int activity_main = 0x7f0f001c;
Copy the code
Do you see the difference? The resource added to the Module is less final. Let’s look at the mainActivity.class file again. We can see that the resource reference here is using a static variable rather than using the value of the resource directly.
public class MainActivity extends AppCompatActivity {
public MainActivity() { } protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.setContentView(layout.activity_main); }}Copy the code
Why do you do that
On Android, if you add a resource to your Module, take activity_main.xml for example. What happens if we assume that the module is also final? First, the resource is replaced with a value in the code compiled by the module. Second, after the Module is added to the main project, if there is a resource with the same name in the main project, the resource in the Module will be replaced. Third, an ID is regenerated for the resource in the main project; Eventually it will appear that the resource ID in the module cannot be found. This is why resource ID declarations in modules are not final.
For details on resource merging rules, see Google’s official documentation
https://developer.android.com/studio/write/add-resources.html.
Causes several phenomena
1. This is why the Module uses the resources of the main project when the main project has the same resources as the Module.
2. This is why we can’t use switch-case for resources in Modules.
3. This is why we cannot use Butterknife directly in modules, as the attributes of annotations need to be final. Butterknife now provides a solution, of course. If you want to use Gradle to copy r.Java and name it r2.java, all r2.java resource declarations are final. This avoids the grammar check. Of course, the resource declarations in R. Java are used in the bytecode compiled with Butterknife.
Author’s brief introduction Peng Tao (@ Peng Tao me) to make technology to understand and interesting personal blog: http://pengtao.me, making address: https://github.com/CPPAlien