Android DataBinding引用同布局XML视图报找不到标识符错误
数据绑定引用同布局视图ID报“找不到标识符”的解决方法
问题复现
在使用Android数据绑定编写布局时,尝试在Button的onClick lambda表达式中直接传入同布局下其他视图的ID给绑定方法:
<Button android:id="@+id/button" android:onClick="@{(v) -> events.userClicked(another_layout_id)}" android:text="Click me" />
相关代码上下文:
events是布局<data>块中提前声明的绑定变量userClicked()方法定义为可接收View类型的入参another_layout_id是和Button同属一个<layout>根标签、但处于不同视图嵌套层级的视图ID
按照数据绑定的语法规则,同布局内带ID的视图可以直接在绑定表达式中引用,但实际编译时抛出cannot find identifier(找不到标识符)错误。
完整出问题的布局代码如下:
<layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"> <data> <variable name="state" type="bindingModel" /> <variable name="events" type="DataModel" /> </data> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="label"/> <androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/another_layout_id" android:layout_width="match_parent" android:layout_height="wrap_content"> <androidx.constraintlayout.helper.widget.Flow android:id="@+id/flow_layout" android:layout_width="0dp" android:layout_height="wrap_content" app:flow_horizontalGap="8dp"/> </androidx.constraintlayout.widget.ConstraintLayout> <Button android:id="@+id/show_all" style="@style/TextButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="@{(v) -> events.userClicked(another_layout_id)}" android:text="Click me" /> </androidx.constraintlayout.widget.ConstraintLayout> </layout>
错误原因
这个问题90%以上的情况是以下两个原因导致的:
- 增量编译缓存异常:新增/修改视图ID后,Android Studio的增量编译没有重新生成完整的绑定类字段列表,导致新添加的ID没有被识别到。
- 旧版本AGP的跨层级ID识别bug:在Android Gradle插件版本低于7.0时,数据绑定编译器存在已知问题:如果被引用的视图和当前引用点的视图不在同一个直接父容器下,直接写ID会无法被识别,哪怕两个视图同属一个根布局。
额外注意:上述布局里,内层ConstraintLayout、Flow控件作为外层ConstraintLayout的直接子View,都没有添加必要的
layout_constraintXxx约束属性,虽然这不是直接导致ID找不到的原因,但这类XML语法警告在个别版本的编译器里也会干扰绑定类的正常生成。
解决方法
按照优先级从高到低尝试以下方案:
- 清理缓存重新编译:点击菜单栏的
Build > Clean Project,等清理完成后再执行Build > Rebuild Project,绝大多数缓存导致的识别问题都能直接解决。 - 补全布局约束:给没有约束的子View补上正确的约束规则:
- 给id为
another_layout_id的内层ConstraintLayout补上相对于外层容器和上方TextView的约束 - 给id为
flow_layout的Flow控件补上相对于内层父容器的约束
补全后再次重新编译即可。
- 给id为
- 兼容旧版本AGP的写法:如果使用的是7.0以下版本的AGP,不想升级插件的话,不要直接引用ID,换用通用API获取目标View即可:把
onClick表达式改成通过当前点击的View拿到根视图,再通过findViewById获取目标View传入,示例代码:
这种写法不依赖数据绑定的ID自动识别逻辑,所有版本都能正常生效。android:onClick="@{(v) -> events.userClicked(v.getRootView().findViewById(R.id.another_layout_id))}"
内容的提问来源于stack exchange,提问作者Gil Ong
相关产品推荐
相关产品推荐

