java.lang.NullPointerException: 缺少必需的视图ID:

88

Android Studio 3.6

在 app/build.gradle 文件中:

android {
viewBinding.enabled = true

这是我的xml代码:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/bluetoothBottonMainContainer"
        android:layout_width="0dp"
        android:layout_height="104dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <View
            android:id="@+id/viewPointNotSelect"
            android:layout_width="16dp"
            android:layout_height="16dp"
            android:background="@drawable/circle_transparent"
            app:layout_constraintBottom_toBottomOf="@+id/separator"
            app:layout_constraintEnd_toStartOf="@+id/separator"
app:layout_constraintTop_toTopOf="parent" />

同时还有另一个XML文件包含了之前的XML文件:

 <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/bottonContainer"
        android:layout_width="0dp"
        android:layout_height="104dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent">

        <include
            android:id="@+id/qrBottonContainer"
            layout="@layout/qr_bottom_container"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent" />

这是我的活动:

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = QrBluetoothSwipeActivityBinding.inflate(layoutInflater)
        setContentView(binding.root)
}

应用已构建并运行。不错。

现在我将id - android:id="@+id/bluetoothBottonMainContainer" 移到外部容器中,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/bluetoothBottonMainContainer"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="0dp"
        android:layout_height="104dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <View
            android:id="@+id/viewPointNotSelect"
            android:layout_width="16dp"
            android:layout_height="16dp"
            android:background="@drawable/circle_transparent"
            app:layout_constraintBottom_toBottomOf="@+id/separator"
            app:layout_constraintEnd_toStartOf="@+id/separator"
            app:layout_constraintTop_toTopOf="parent" />

应用程序已构建,但在运行时出现了以下行的运行时错误:

binding = QrBluetoothSwipeActivityBinding.inflate(layoutInflater)

错误:

10-25 11:11:51.290 E/AndroidRuntime(14128): FATAL EXCEPTION: main
10-25 11:11:51.290 E/AndroidRuntime(14128): Process: com.myproject.debug, PID: 14128
10-25 11:11:51.290 E/AndroidRuntime(14128): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.myproject.debug/com.myproject.ui.actviity.QRBluetoothSwipeActivity}: java.lang.NullPointerException: Missing required view with ID: bluetoothBottonMainContainer
10-25 11:11:51.290 E/AndroidRuntime(14128):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
10-25 11:11:51.290 E/AndroidRuntime(14128):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
10-25 11:11:51.290 E/AndroidRuntime(14128):     at android.app.ActivityThread.-wrap11(ActivityThread.java)
10-25 11:11:51.290 E/AndroidRuntime(14128):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
10-25 11:11:51.290 E/AndroidRuntime(14128):     at android.os.Handler.dispatchMessage(Handler.java:102)
10-25 11:11:51.290 E/AndroidRuntime(14128):     at android.os.Looper.loop(Looper.java:148)
10-25 11:11:51.290 E/AndroidRuntime(14128):     at android.app.ActivityThread.main(ActivityThread.java:5417)
10-25 11:11:51.290 E/AndroidRuntime(14128):     at java.lang.reflect.Method.invoke(Native Method)
10-25 11:11:51.290 E/AndroidRuntime(14128):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
10-25 11:11:51.290 E/AndroidRuntime(14128):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
10-25 11:11:51.290 E/AndroidRuntime(14128): Caused by: java.lang.NullPointerException: Missing required view with ID: bluetoothBottonMainContainer
10-25 11:11:51.290 E/AndroidRuntime(14128):     at com.myproject.databinding.BluetoothBottomContainerBinding.bind(BluetoothBottomContainerBinding.java:114)
10-25 11:11:51.290 E/AndroidRuntime(14128):     at com.myproject.databinding.QrBluetoothSwipeActivityBinding.bind(QrBluetoothSwipeActivityBinding.java:76)
10-25 11:11:51.290 E/AndroidRuntime(14128):     at com.myproject.databinding.QrBluetoothSwipeActivityBinding.inflate(QrBluetoothSwipeActivityBinding.java:62)
10-25 11:11:51.290 E/AndroidRuntime(14128):     at com.myproject.databinding.QrBluetoothSwipeActivityBinding.inflate(QrBluetoothSwipeActivityBinding.java:52)
10-25 11:11:51.290 E/AndroidRuntime(14128):     at com.myproject.ui.actviity.QRBluetoothSwipeActivity.onCreate(QRBluetoothSwipeActivity.kt:31)
10-25 11:11:51.290 E/AndroidRuntime(14128):     at android.app.Activity.performCreate(Activity.java:6251)
10-25 11:11:51.290 E/AndroidRuntime(14128):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
10-25 11:11:51.290 E/AndroidRuntime(14128):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
10-25 11:11:51.290 E/AndroidRuntime(14128):     ... 9 more
10-25 11:11:51.291 W/ActivityManager(  780):   Force finishing activity com.myproject.debug/com.myproject.ui.actviity.QRBluetoothSwipeActivity
10-25 11:11:51.307 I/Icing   (11529): Indexing done com.google.android.gms-apps

4
将产生 NPE 的视图的 ID 重命名为“drawerLayout_main”对我很有用。 这将 drawerLayout 视图更名为 drawerLayout_main,解决了我的问题。 - 11m0
11
嗨,当使用合并标记时,您需要格外小心。我已经撰写了一篇博客文章,完整地解释了视图绑定以及为什么合并标记不那么容易使用。请查看Androidbites|ViewBinding - Chetan Gupta
@11m0 请创建一个答案,以便我可以点赞。这是唯一对我们有用的答案! - MidasLefko
33个回答

91
如果开启了TabLayoutViewBinding,若是遇到此问题,那么您可能为TabItem设置了id。删除TabItem的id对我的问题进行了解决。
更新:对于那些想要在没有idViewPager2的情况下切换选项卡的人,这里有推荐使用TabLayoutMediator的文档:

使用ViewPager2创建带有选项卡的滑动视图


2
在启用了ViewBinding的情况下,有没有其他方法可以添加TabItem的ID? - Narayan soni
5
原因见 https://dev59.com/Nb_qa4cB1Zd3GeqPLJkn#66325932。 - Chee-Yi

73
请检查一下,也许你在不同的模块中有相同的布局文件。

7
非常感谢!问题出在两个不同功能模块中具有相同名称的布局。 - P1NG2WIN
3
我的多模块情况的最佳答案。谢谢。 - Ehma Africa
2
谢谢!这也是我的问题。尽管其中一个模块未被应用程序使用,但仍然发生了这种情况。 - Elyes Mansour
1
这就是发生在我身上的事情!我在应用程序模块中有一个同名的xml文件,它替换了另一个模块中的xml文件并导致了NPE错误。 - Jeff
1
没错,非常有帮助。 - Mohammed_7aafar
显示剩余3条评论

51

我遇到了这个问题,但是在我的情况下问题是 include 标志。我发现的解决方法是使包含的布局的根视图 ID 与视图 ID 相同。

activity_layout.xml

<LinearLayout>
    <include android:id="@+id/widget1" layout="@layout/my_widget" />
</LinearLayout>

my_widget.xml

<LinearLayout
    android:id="@+id/widget1">
</LinearLayout>

3
我同意,这很愚蠢。我的解决方案是保留include标记的id,并在include标记的布局引用中删除constraintLayout顶层的id。 - cking24343
3
难以置信使用相同的名称对我实际有效。 - Jenish
谢谢!在我的情况下,我还为包含的布局声明了不同的绑定。使用根布局就足够了。 - Joan
1
自 AGP 4.0 或更高版本以后,此项操作已不再是必须的。 - Jake Wharton
将id添加到</include/>标签中解决了该问题。AndroidStudio 4.0 - 4.1 - Volodymyr R.tmnko

47

注意,如果您在所包含的布局XML中使用<merge>,那么逻辑是不同的,正如此处所指出的:
深入探索Android View Binding

如果我们尝试为其设定ID,则视图绑定将无法在绑定类中生成该ID,因此我们无法像普通include一样访问该视图。
在这种情况下,我们有一个PlaceholderBinding,它是placeholder.xml(我们的<merge>布局文件)的自动生成类。我们必须调用其bind()方法,并传递包含它的布局的根视图。

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<include layout="@layout/placeholder" />

</androidx.constraintlayout.widget.ConstraintLayout>
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
        binding = FragmentOrderBinding.inflate(layoutInflater, container, false)
        placeholderBinding = PlaceholderBinding.bind(binding.root)
        placeholderBinding.tvPlaceholder.text = getString(R.string.please_wait)
        return binding.root
    }

4
非常好的答案,救了我一命。在我的情况下,这是一个自定义视图,由于包含布局有合并标记,所以无法检索它。 - j2emanue
1
这个问题的答案应该被接受。 - Mahmoud Omara
解决方案:不要给包含的布局设置id。 - Amr
1
如何在约束布局中对包含的视图进行对齐? - Булат Мухутдинов
1
谢谢,这就是我在合并时遇到的问题。 - Mikkel Larsen
1
谢谢,这就是我在合并时遇到的问题。 - undefined

22

27
状态固定了吗?当然没有。我仍然有这个问题。 - Paradoxy
3
我使用的是从2020年12月2日开始的Android Studio 3.6,但对于我的某些活动,问题仍未消失。我有一个LinearLayout,其中包含TabLayout、ViewPager等子项。我的TabLayout本身有3个选项卡项。我得到了缺少必需视图ID的选项卡项目的错误。当我删除它们的ID时,此错误消失了。我使用简单的ID,如@id/tabitem等。该活动还具有带有导航的抽屉布局。通过使用ViewBinding,即使调用了 .setDisplayHomeAsUpEnabled(true),其开关也会消失。最后,我添加了tools:viewBindingIgnore="true",并使用了那个老旧的findviewbyid。 - Paradoxy
4
当我使用<merge>布局动态添加视图时,例如:parent_layout.xml使用MyMergeLayoutBinding.inflate(inflater, viewGroup, false)parent_layout.xml的子项添加视图时,我仍然遇到了错误,因为my_merge_layout.xml使用<merge>作为父标签。 - mochadwi
2
至今仍然存在问题,使用 AS v3.6.1 和 AGP v3.6.1。 - Erik
3
我仍然在4.0.1版本(主要版本)中遇到此问题。 - paul_f
显示剩余10条评论

10
你应该删除TabItem的id并使用TabLayout API来获取该项,如果你正在使用Material Design,则此解决方法有效。
参考链接:Github答案

10

如果您在RecyclerView中将单元格与视图错误地绑定,也会出现此错误。 如果将视图绑定到错误的布局,则会出现错误,指出它无法找到预期的子视图。

这让我感到困惑了很长时间。

解决方案是确保您将布局与ViewBinding绑定到的视图相同。

例如,请确保:

R.layout.my_new_view

必然会:

MyNewViewBinding

否则你会收到这个错误提示。


4
在我的情况下,另一个模块中有一个同名的文件。
我在A模块和B模块中都有item_view.xml,因此数据绑定无法区分它们。
我更改了其中一个文件的名称,问题得到了解决。

和我一样;我的问题也是与数据绑定有关。我复制并粘贴了布局代码,因为我有两个类似的布局,但我忘记将第二个布局与其视图模型相关联。它仍然与其他视图模型相关联,并且变量名称不同,因此绑定崩溃,显示“缺少所需的ID视图:” - Daniel Cettour

3

这正在发生在我的设备上。我刚刚注意到,这是因为我在我的xml文件中(让我们称它们为:Activity_main.xml / Activity_other.xml),我曾经有一个小部件(在这种情况下是一个按钮)具有相同的id(+id/bttNext)

(也就是说activity_main.xmlactivity_other.xml都使用了具有相同+id的按钮)

当我在设备上测试我的应用程序时:

java.lang.NullPointerException:缺少所需的视图ID:

就会出现这个问题

当我把第二个活动的按钮的+id改变(假设重命名为bttNext1)时,应用程序就能正常运行了

总之:不要在按钮(及其他小部件)中使用相同的id, 不管它们是否在单独的活动中


3
解决方案是删除主容器的ID,并在父容器内放置其他容器。
1. 布局
    <include
    android:id="@+id/example"
    layout="@layout/account_current_payment_card"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"/>
    

2.- 包含布局

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/example2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent">
    </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接