登录

去注册

登录

注册

去登录

注册

每日一问 为什么Android app module下的R.java中变量为final,而lib module中R.java中的变量非final呢?

xiaoyang   2019-07-28   收藏

一次在把app module修改为lib module时发现,switch竟然要改成if else ,从而发现这个问题。


为什么呢?


有什么好的解决方案?

3

1.R文件是编译器生成的

2.lib module可以打成aar模式,注意这里的aar里面的jar是不包含R.class的,反而会是包含一个R.txt


为什么aar里面的jar不直接包含R.class呢?

这要设计R文件的id分配,默认是从0x7f + resId + 0001开始分配的

int anim mintegral_reward_activity_open 0x7f010001
int anim mintegral_reward_activity_stay 0x7f010002


int attr alpha 0x7f040001
int attr coordinatorLayoutStyle 0x7f040002


int id RelativeLayout1 0x7f0c0001
int id account 0x7f0c0002

可见都是从0x7fXX0001开始分配的



那么假如有两个lib目录a和b,并且都有资源文件

肯定会有资源冲突的,因为每个lib都是从0x7fXX0001开始分配的


这里,as会自动处理冲突,会重定位资源id的开始区间,使得a的资源区间是从0x7fXX00XX开始

b的资源区间从另外一个开始,这样就不会有资源冲突了


处理冲突默认是按照字母顺序排序的,从a到z排序

public static final class layout {
public static final int abc_action_bar_title_item = 2131296256;   // 7f090000

public static final int abc_action_bar_up_container = 2131296257;  // 7f090001

public static final int abc_action_menu_item_layout = 2131296258;
public static final int abc_action_menu_layout = 2131296259;
public static final int abc_action_mode_bar = 2131296260;
public static final int abc_action_mode_close_item_material = 2131296261;
public static final int abc_activity_chooser_view = 2131296262;
public static final int abc_activity_chooser_view_list_item = 2131296263;
public static final int abc_alert_dialog_button_bar_material = 2131296264;
public static final int abc_alert_dialog_material = 2131296265;
public static final int abc_alert_dialog_title_material = 2131296266;
public static final int abc_cascading_menu_item_layout = 2131296267;
public static final int abc_dialog_title_material = 2131296268;
public static final int abc_expanded_menu_layout = 2131296269;
public static final int abc_list_menu_item_checkbox = 2131296270;
public static final int abc_list_menu_item_icon = 2131296271;
public static final int abc_list_menu_item_layout = 2131296272;
public static final int abc_list_menu_item_radio = 2131296273;
public static final int abc_popup_menu_header_item_layout = 2131296274;
public static final int abc_popup_menu_item_layout = 2131296275;
public static final int abc_screen_content_include = 2131296276;
public static final int abc_screen_simple = 2131296277;
public static final int abc_screen_simple_overlay_action_mode = 2131296278;
public static final int abc_screen_toolbar = 2131296279;
public static final int abc_search_dropdown_item_icons_2line = 2131296280;
public static final int abc_search_view = 2131296281;
public static final int abc_select_dialog_material = 2131296282;
public static final int abc_tooltip = 2131296283;
public static final int activity_lib = 2131296284;
public static final int activity_main = 2131296285;
public static final int notification_action = 2131296286;
public static final int notification_action_tombstone = 2131296287;
public static final int notification_template_custom_big = 2131296288;
public static final int notification_template_icon_group = 2131296289;
public static final int notification_template_part_chronometer = 2131296290;
public static final int notification_template_part_time = 2131296291;
public static final int select_dialog_item_material = 2131296292;
public static final int select_dialog_multichoice_material = 2131296293;
public static final int select_dialog_singlechoice_material = 2131296294;
public static final int support_simple_spinner_dropdown_item = 2131296295;
}


是最后在编译apk时候,才能确定每个资源id的值


其实lib module 应该来说并没有R.java 文件,只是as的一个语法支持

在编译成apk时候会最终确定每个资源id的值

但最终每个lib库里面的R.class文件里面的值会是final类型的

回复
axx123 : @axx123 

因为编译器的语法优化,会将R.id.axx替换成具体的210312344,而lib的资源id是还会变的,所以lib的资源id是不能用final声明的

2019-07-26 回复
axx123 : @axx123 

在Android Studio 中将光标移动到switch关键字并按Alt+ Enter然后选择 将'switch'替换为'if'。

2019-07-26 回复
3

在Java语法中,switch的参数必须是常量或者值,否则会报语法错误。所以我们一定会出现把 application 的 switch 移动到 module 的时候,报了语法错误,修改为 if-else 完美解决。


那为什么 application 下面的 R.java 都是静态常量,而 library 下面的 R.java 文件都是静态变量呢?


其实不难理解,我们在不同的 module 其实是可以设置一样的变量名称的,比如application下有layout_main.xml,在library里面也可以有这样的。如果你两个都是静态常量,怎么弄?在者,假设你在 application 编译 setContent(R.layout.layout_main),你也会在debug下发现它其实一个固定的值。所以合并的时候,你能知道我使用的是哪个么?


可以看看官方文档:https://developer.android.com/studio/write/add-resources.html

回复
0

其实很简单,如果lib中 R.java 文件里面的变量是 final 的,那么会有两个问题:

  • 编译速度:每次编译都需要将所有的资源与代码都编译一次,以免变量值产生碰撞
  • lib无法复用:如果生成的值是 final 的,那么这个lib给别人用的时候,值很可能与其他 lib 一样,导致问题
回复
0

那到底有没有解决方案?转化成if-else就是解决方案?不还是不能用么。

回复
0

解决方案, 光标指到switch,利用Alt+ Enter然后选择 将'switch'替换为'if'。

回复
0
回复

删除留言

确认删除留言,会导致相关评论丢失?

取消 确定