为何Android Studio设计器在约束中使用@+id而非@id?
关于Android布局中@id和@+id的那些“矛盾”细节
这确实是个挺有意思的细节,我当初刚接触Android布局的时候也对这个点困惑过!先从大家熟知的规则说起,再拆解这个看似矛盾的现象。
常规认知里的@id和@+id规则
咱们平时学到的、官方文档和热门问答里明确的规则是这样的:
@+id/xxx:用来创建新的ID资源,通常配合android:id属性使用。@告诉XML解析器要把后面的内容当作资源ID处理,+则标记这是一个需要新增到R.java文件里的资源名称,aapt工具会为它生成对应的整数ID。@id/xxx:用来引用已经存在的ID资源,可以是你自己定义的,也可以是Android系统自带的(系统ID需要加android:命名空间,比如@android:id/action_bar)。引用系统ID时不需要加+,因为这些ID已经在系统资源里存在了。
奇怪的现象:重复用@+id引用已存在的ID居然不报错?
就像你发现的那样,在Android Studio的可视化编辑器里用ConstraintLayout(其实其他布局也有类似情况)添加约束时,会生成类似这样的代码:
app:layout_constraintTop_toBottomOf="@+id/rlistfrag"
但这个rlistfrag明明已经在同一个布局文件里被其他元素用android:id="@+id/rlistfrag"定义过了。按照之前的规则,这相当于两次声明“要创建新ID”,但实际运行和编译都不会出问题——除非你在多个android:id属性里用同一个ID,那才会引发冲突。
被忽略的关键语义:@+id的真正含义是“不存在则创建”
其实官方文档里有个容易被忽略的细节,+的真正语义并不是“必须创建新ID”,而是**“如果这个ID还不存在,就创建它”**:
- 当aapt工具解析布局文件时,会按顺序扫描所有的ID引用。只要第一次遇到
@+id/xxx(不管是在android:id属性里,还是在约束、跳转这类引用属性里),就会在R.java里生成对应的整数ID; - 如果之后再遇到
@+id/xxx,只要这个ID已经存在,aapt就会自动把它当作普通的@id/xxx来处理,不会重复创建,也不会抛出错误。
为什么Android Studio的设计器要这么做?
这其实是工具为了提升开发者体验做的兼容设计:
- 可视化编辑器无法保证你操作的顺序——比如你可能先给元素A添加约束到元素B,再去给元素B设置ID。如果工具用
@id/xxx,这时候解析就会因为“ID未定义”报错; - 统一用
@+id/xxx的话,不管元素的定义顺序如何,只要ID不存在就创建,存在就直接引用,完美避免了因解析顺序导致的编译错误。对新手来说也更友好,不用纠结什么时候该用+什么时候不用。
总结一下:这种写法并没有违背官方规则,只是文档的描述没有把这种兼容场景讲得太透,核心逻辑还是“ID在首次被@+id引用时创建”,后续的@+id都会自动降级为普通引用。
内容的提问来源于stack exchange,提问作者wholerabbit
相关产品推荐
相关产品推荐

