【问题标题】:java.lang.IllegalStateException: view!!.findViewById(R.id.dog_image) must not be nulljava.lang.IllegalStateException: view!!.findViewById(R.id.dog_image) 不能为空
【发布时间】:2025-11-28 04:15:02
【问题描述】:

我正在使用 Android Studio 和 Kotlin。我正在尝试创建一个 RecyclerView 和一个 Adapter。

当我尝试使用 RecyclerView 时出现以下错误。它说 dog_image 为空,但我不明白为什么。

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.dogglers, PID: 26356
    java.lang.IllegalStateException: view!!.findViewById(R.id.dog_image) must not be null
        at com.example.dogglers.adapter.DogCardAdapter$DogCardViewHolder.<init>(DogCardAdapter.kt:50)
        at com.example.dogglers.adapter.DogCardAdapter.onCreateViewHolder(DogCardAdapter.kt:90)
        at com.example.dogglers.adapter.DogCardAdapter.onCreateViewHolder(DogCardAdapter.kt:34)
        at androidx.recyclerview.widget.RecyclerView$Adapter.createViewHolder(RecyclerView.java:7078)
        at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6235)
        at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6118)
        at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6114)
        at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2303)
        at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1627)
        at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1587)
        at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:665)
        at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4134)
        at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:3851)
        at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4404)
        at android.view.View.layout(View.java:20871)
        at android.view.ViewGroup.layout(ViewGroup.java:6268)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
        at android.view.View.layout(View.java:20871)
        at android.view.ViewGroup.layout(ViewGroup.java:6268)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
        at android.view.View.layout(View.java:20871)
        at android.view.ViewGroup.layout(ViewGroup.java:6268)
        at androidx.appcompat.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:530)
        at android.view.View.layout(View.java:20871)
        at android.view.ViewGroup.layout(ViewGroup.java:6268)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
        at android.view.View.layout(View.java:20871)
        at android.view.ViewGroup.layout(ViewGroup.java:6268)
        at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1812)
        at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1656)
        at android.widget.LinearLayout.onLayout(LinearLayout.java:1565)
        at android.view.View.layout(View.java:20871)
        at android.view.ViewGroup.layout(ViewGroup.java:6268)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
        at com.android.internal.policy.DecorView.onLayout(DecorView.java:758)
        at android.view.View.layout(View.java:20871)
        at android.view.ViewGroup.layout(ViewGroup.java:6268)
        at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2972)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2487)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1580)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7634)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:958)
        at android.view.Choreographer.doCallbacks(Choreographer.java:770)
        at android.view.Choreographer.doFrame(Choreographer.java:702)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:944)
        at android.os.Handler.handleCallback(Handler.java:873)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:201)
        at android.app.ActivityThread.main(ActivityThread.java:6831)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:927)


错误在这里(适配器):

/*
* Copyright (C) 2021 The Android Open Source Project.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.dogglers.adapter

import android.content.Context
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.example.dogglers.model.Dog
import com.example.dogglers.data.DataSource.dogs as list_dogs
import com.example.dogglers.R

/**
 * Adapter to inflate the appropriate list item layout and populate the view with information
 * from the appropriate data source
 */
class DogCardAdapter(
    private val context: Context?,
    private val layout: Int
): RecyclerView.Adapter<DogCardAdapter.DogCardViewHolder>() {

    // TODO: Initialize the data using the List found in data/DataSource
    private val dogs: List<Dog> = list_dogs


    /**
     * Initialize view elements
     */
    class DogCardViewHolder(view: View?): RecyclerView.ViewHolder(view!!) {
        // TODO: Declare and initialize all of the list item UI components


        val imageView: ImageView = view!!.findViewById(R.id.dog_image)

        val dogNameTextView: TextView = view!!.findViewById(R.id.dog_name)
        val dogAgeTextView: TextView = view!!.findViewById(R.id.dog_age)
        val dogHobbiesTextView: TextView = view!!.findViewById(R.id.dog_hobbies)




    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DogCardViewHolder {
        // TODO: Use a conditional to determine the layout type and set it accordingly.
        //  if the layout variable is Layout.GRID the grid list item should be used. Otherwise the
        //  the vertical/horizontal list item should be used.
        var adapterLayout =LayoutInflater.from(parent.context)
            .inflate(R.layout.activity_grid_list, parent, false)

        when(layout){
            1->{

                adapterLayout =LayoutInflater.from(parent.context)
                    .inflate(R.layout.activity_vertical_list, parent, false)

            }

            2->{
                adapterLayout =LayoutInflater.from(parent.context)
                    .inflate(R.layout.activity_horizontal_list, parent, false)
            }

        }

        // TODO Inflate the layout

        // TODO: Null should not be passed into the view holder. This should be updated to reflect
        //  the inflated layout.

        return DogCardViewHolder(adapterLayout)
    }

    override fun getItemCount(): Int {
        return dogs.size
    }// TODO: return the size of the data set instead of 0

    override fun onBindViewHolder(holder: DogCardViewHolder, position: Int) {
        // TODO: Get the data at the current position
        // TODO: Set the image resource for the current dog
        // TODO: Set the text for the current dog's name
        // TODO: Set the text for the current dog's age
        val resources = context?.resources
        val dog = dogs[position]
        holder.imageView.setImageResource(dog.imageResourceId)
        holder.dogNameTextView.text=dog.name
        holder.dogAgeTextView.text=dog.age

        // TODO: Set the text for the current dog's hobbies by passing the hobbies to the
        //  R.string.dog_hobbies string constant.
        //  Passing an argument to the string resource looks like:
        //  resources?.getString(R.string.dog_hobbies, dog.hobbies)

        holder.dogHobbiesTextView.text=resources?.getString(R.string.dog_hobbies, dog.hobbies)

    }
}


dog_image id 位于以下 XML 档案中。不知道为什么是null:

我想知道如何改进这个问题

【问题讨论】:

  • 您能发布您的完整回收站视图适配器代码吗?
  • 好的,谢谢。我要改进这个问题。我已经更新了问题
  • layout.activity_horizo​​ntal_list 中有 dog_image ImageView 吗?因为你还没有分享这个布局的代码。
  • 这不是您的问题,但您的布局不正确。首先,无论它是否应该是一个网格,你都会对一个网格布局项进行膨胀。您不想夸大一次性布局,因为这会在显示视图时造成不必要的延迟。然后,你的when 的两个分支都会膨胀相同的东西。

标签: android xml android-studio kotlin android-layout


【解决方案1】:

教程明确指出

onCreateViewHolder() 中,您想要扩展grid_list_itemvertical_horizontal_list_item 布局。

在您的代码中,首先您要对activity_grid_list 进行膨胀,然后用activity_vertical_listactivity_horizontal_list 覆盖它。

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DogCardViewHolder {
    // TODO: Use a conditional to determine the layout type and set it accordingly.
    //  if the layout variable is Layout.GRID the grid list item should be used. Otherwise the
    //  the vertical/horizontal list item should be used.

    when(layout) {
        Layout.GRID->{
            adapterLayout = LayoutInflater.from(parent.context)
                    .inflate(R.layout.grid_list_item, parent, false)
        }
        // use this, or "else->"
        Layout.VERTICAL, Layout.HORIZONTAL->{
            adapterLayout = LayoutInflater.from(parent.context)
                    .inflate(R.layout.vertical_horizontal_list_item, parent, false)
        }

    }

    // TODO Inflate the layout

    // TODO: Null should not be passed into the view holder. This should be updated to reflect
    //  the inflated layout.

    return DogCardViewHolder(adapterLayout)
}

【讨论】:

    【解决方案2】:

    dog_image 应该存在于每个可以在onCreateViewHolder 中膨胀的布局下 意思:

    activity_grid_list
    activity_vertical_list
    activity_horizontal_list
    

    如果您将其添加到这些布局中,代码将运行。 但是,我认为这不是您要寻找的,如果我理解正确,您希望将列表作为适配器项进行膨胀,这意味着您应该有另一个适配器来处理这些列表的项,并且该适配器应该使 dog_image 膨胀。

    【讨论】:

    • 你好,我不知道应该把activity_grid_listactivity_vertical_list和activity_horizo​​ntal_list放在哪里。我是新来的。我在做教程
    • 我不太了解你。对不起。我正在做教程developer.android.com/codelabs/…
    • 嘿!如果您不确定您的回答是否对 OP 有帮助,那么您可以将您的意见放在评论部分。谢谢!继续贡献!
    • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center