Home > Software design >  java.lang.IllegalStateException: view!!.findViewById(R.id.dog_image) must not be null
java.lang.IllegalStateException: view!!.findViewById(R.id.dog_image) must not be null

Time:12-04

I am working with Android Studio and Kotlin. I am trying to create an RecyclerView and a Adapter.

I obtain the following error when I try to use the RecyclerView. It says that dog_image is null but I don't undernstand why.

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)


The error is here (Adapter):

/*
* 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 is in the following XML archives. I don't know why is null:

file grid_list_item

file vertical_horizontal_list_item

I would like to know how to improve this question

CodePudding user response:

dog_image should live under each layout that could be inflated in onCreateViewHolder meaning:

activity_grid_list
activity_vertical_list
activity_horizontal_list

if you will add it to those layout the code will run. However, I don't think that's what you are looking for, if I understood correctly you want to inflate list's as adapter items, meaning you should have another adapter that will handle those list's item's an that adapter should inflate the dog_image.

CodePudding user response:

The tutorial clearly states that

In onCreateViewHolder(), you want to either inflate the grid_list_item or vertical_horizontal_list_item layout.

In your code, first you're inflating activity_grid_list, and then overriding it with activity_vertical_list or activity_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)
    }
  • Related