导入外部类库自动生成各自的R类(选摘)

来源:互联网 发布:淘宝网店装修设计师 编辑:程序博客网 时间:2024/06/05 00:30
Nature of Resources in Application and Library Projects
In previous releases, this inclusion of libraries was source-code based. This meant that 
every time the main project was compiled, all the library source files had to be compiled 
as well. In the new scheme, the libraries are precompiled and included in the target 
application as JAR files.  
This compile-time assimilation of libraries poses a couple of unexpected challenges
Previously, the  R.java file for the application project  was regenerated when things were 
compiled in the target application, including the library source files. This meant that if 
you had ten different libraries,  R.java was generated once for all of them, and the 
generated IDs could be guaranteed to be unique.
However, when you precompile, these 
IDs belonging to the library  projects can get frozen in the compiled JAR files. This will 
lead to duplicated IDs.  

To fix this, Android has temporarily used a local R.java file for a library to generate the 
necessary Java classes, but it  doesn’t package the corresponding R.class  in the 
generated JAR file for that library project. Instead, it relies on the R.java file that is re-created and made available in the application project. As long as the application project 
has an R.java file under the same Java package as  the library project, the scheme will 
work. Figure 16–7 shows how Android has multiple R.java classes/files in the  gen  
subdirectory of the application project. You see an R.java file for the application and 
one  R.java file for each of the library projects. 
 
Figure 16–7. Multiple  R.java files in the application project 
There is one more challenge that needs solving  when compiled library JARs are included 
in the target application project. When Android compiles the  Java classes in the library 
project, those Java classes  reference the local library  R.java constants, because at the 
time of compiling the library  project, the library project is  all that is available. The 
application project that uses the library is a future prospect. 
If the library’s  R.java constants were to be declared  static final, then the compiler 
would hard-code the constant numbers (such as 0x7778989 ) in the compiled code. This 
needs to be stopped if you wish to avoid such duplicate numbers from multiple library 
JAR files. The solution Android has adapted is to declare the constants in R.java files as 
non-final. 
Listing 16–11 shows the R.java file created for our  TestLibrary  in the library project. 
Notice that the IDs are not declared final. They are merely  static variables in a Java 
class. Typically, these would have been final as well. 
Listing 16–11.  Non-Final Resource IDs in the Library Project  R.java File 
package com.androidbook.library.testlibrary; public final class R {     public static final class attr {     }     public static final class drawable {         public static int icon=0x7f020000;         public static int robot=0x7f020001;     }     public static final class id {         public static int menuGroup_Main=0x7f050001;         public static int menu_clear=0x7f050002;         public static int menu_testlib_1=0x7f050003;         public static int menu_testlib_2=0x7f050004;         public static int text1=0x7f050000;     }     public static final class layout {         public static int lib_main=0x7f030000;     }     public static final class menu {         public static int lib_main_menu=0x7f040000;     } } 

These IDs in the library version of the R.java file will help with compiling the Java source 
files in the library project. By keeping the IDs as non-final variables, Android prevents the 
values for these IDs from getting (hard-coded) into the compiled java class files for the 
library. 
Now, as you saw in Figure 16–6, these Java JAR files from the library are included into 
the application proj ect. Figure 16–7 also  showed that the  R.java file from the library 
(Listing 16–11) is reproduced in the appli cation project.  Listing 6-12 shows this re-created library’s  R.java file in the application project. 
Listing 16–12.  Re-created  R.java File for the Library’s Resources in the Application Project 
package com.androidbook.library.testlibrary; public final class R {     public static final class attr {     }     public static final class drawable {         public static final int icon=0x7f020000;         public static final int robot=0x7f020001;     }     public static final class id { CHAPTER 16:  Exploring Packages  463         public static final int menuGroup_Main=0x7f060001;         public static final int menu_clear=0x7f060002;         public static final int menu_library_activity=0x7f060005;         public static final int menu_testlib_1=0x7f060003;         public static final int menu_testlib_2=0x7f060004;         public static final int text1=0x7f060000;     }     public static final class layout {         public static final int lib_main=0x7f030000;         public static final int main=0x7f030001;     }     public static final class menu {         public static final int lib_main_menu=0x7f050000;         public static final int main_menu=0x7f050001;     }     public static final class string {         public static final int app_name=0x7f040001;         public static final int hello=0x7f040000;     } } 

All the IDs from the library’s  R.java file are re-created in the duplicated  R.java file of the 
application project. This file also contains IDs from the main  application. It is not entirely 
clear why there is a need to place app constants in the  R.java file belonging to the 
library’s Java package.  
Also, curiously, the  R.java file belonging to the applicatio n’s Java project is identical 
except for the Java package name at the top. Li sting 6-13 contains that file just to show 
you how identical this file is to the one in Listing 16–12. The only difference, as you can 
see, is the Java package name. 
Perhaps this answers the previous question that we have pondered: if there is no harm 
in mixing the main resources and the library’s resources, why create two files? Just 
create one, and copy it with different  Java package names at the top.  
Listing 16–13.  Main Application’s  R.java File Containing Combined Resources
package com.androidbook.library.testlibraryapp; public final class R {     public static final class attr {     }     public static final class drawable {         public static final int icon=0x7f020000;         public static final int robot=0x7f020001;     }     public static final class id {         public static final int menuGroup_Main=0x7f060001;         public static final int menu_clear=0x7f060002;         public static final int menu_library_activity=0x7f060005;         public static final int menu_testlib_1=0x7f060003;         public static final int menu_testlib_2=0x7f060004;         public static final int text1=0x7f060000;     }     public static final class layout {         public static final int lib_main=0x7f030000;         public static final int main=0x7f030001;     } CHAPTER 16:  Exploring Packages  464     public static final class menu {         public static final int lib_main_menu=0x7f050000;         public static final int main_menu=0x7f050001;     }     public static final class string {         public static final int app_name=0x7f040001;         public static final int hello=0x7f040000;     } }

Implication of Runtime Library Dependency

There is an implication tied to the fact that IDs in the library’s  R.java file are not final. It is 
common to use a switch statement to respond to menu items based on a menu item ID. 
This language construct will fail at compile time when done in the library code if the IDs 
are not final. This is because the  case statement in a  switch clause has to be a real, 
constant number, like a  #define  in C.  
So the switch statement in Listing 16–14 will not compile unless the IDs (such as 
R.id.menu_item_1) are actual literal numbers or static finals. 
Listing 16–14.  Sample  switch Statement to Demonstrate Non-Final Variables 

switch(menuItem.getItemId()) {    case R.id.menu_item_1:         Statment1;         break    case 0x7778888: // as an example for R.id.menu_item_2:        statement;        break;    default:        statement; }


原创粉丝点击