Search code examples
androidkotlinandroid-recyclerviewimageviewandroid-imageview

Can't assign an image to a Nullable ImageView


How can I set an image to ImageView?

The idea of my app is to show the different type of RecyclerView's view holder according to the data class in a RecyclerView. Data classes look like this:

abstract class Thing(open val title: String, open val body: String, open val pic: ImageView?)

data class Movie(override val title: String, override val body: String): Thing(title, body, pic = null)
data class Book(override val title: String, override val body: String): Thing(title, body, pic = null)
data class Game(override val title: String, override val body: String, override val pic: ImageView?): Thing(title, body, pic)

Also, I have a MainFragment where I am adding the data manually. Here I am trying to give the name and the description of a game, and also to set the particular image to a game_pic ImageView:

class MainFragment: Fragment() {
private val mMoviesBooksGames = listOf(
  Game("Dixit", "Give the perfect clue so most (not all) players guess the right surreal image card.", game_pic.setImageResource(R.drawable.alias) as ImageView)
  }
}

How I declare the GameViewHolder where my game_pic is:

class GameViewHolder(inflater: LayoutInflater, parent: ViewGroup) :
    ThingViewHolder(inflater.inflate(R.layout.game_list_item, parent, false)) {
    private var mGameTitleView: TextView? = null
    private var mGameDescriptionView: TextView? = null
    private var mGamePicImageView: ImageView? = null

    init {
        mGameTitleView = itemView.findViewById(R.id.game_title)
        mGameDescriptionView = itemView.findViewById(R.id.game_description)
        mGamePicImageView = itemView.findViewById(R.id.game_pic)
    }

    override fun bind(dataToBind: Thing) {
        mGameTitleView?.text = ">> Book ${dataToBind.title}"
        mGameDescriptionView?.text = dataToBind.body
        mGamePicImageView = dataToBind.pic
    }
}

An error that I get after using game_pic.setImageResource(R.drawable.alias) as ImageView is:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.recyclerview, PID: 822
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.recyclerview/com.example.recyclerview.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ImageView.setImageResource(int)' on a null object reference
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3555)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3707)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2220)
        at android.os.Handler.dispatchMessage(Handler.java:107)
        at android.os.Looper.loop(Looper.java:237)
        at android.app.ActivityThread.main(ActivityThread.java:8019)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1100)
     Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ImageView.setImageResource(int)' on a null object reference
        at com.example.recyclerview.MainFragment.<init>(MainFragment.kt:33)
        at com.example.recyclerview.MainFragment$Companion.newInstance(MainFragment.kt:67)
        at com.example.recyclerview.MainActivity.createFragment(MainActivity.kt:4)
        at com.example.recyclerview.MainActivity.createFragment(MainActivity.kt:3)
        at com.example.recyclerview.SingleFragmentActivity.onCreate(SingleFragmentActivity.kt:25)
        at android.app.Activity.performCreate(Activity.java:7957)
        at android.app.Activity.performCreate(Activity.java:7946)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1307)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3530)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3707) 
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83) 
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2220) 
        at android.os.Handler.dispatchMessage(Handler.java:107) 
        at android.os.Looper.loop(Looper.java:237) 
        at android.app.ActivityThread.main(ActivityThread.java:8019) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1100) 
I/Process: Sending signal. PID: 822 SIG: 9

Solution

  • data class Game(
        override val title: String, 
        override val body: String,
        override val image: Int)
    

    modify the data class like this

    override fun bind(dataToBind: Thing) {
        mGameTitleView?.text = ">> Book ${dataToBind.title}"
        mGameDescriptionView?.text = dataToBind.body
        mGamePicImageViewsetImageResource(dataToBind.pic)
    }
    

    after that write replace the code into your view holder like this

    data class Game(
        "Dixit", 
        "Give the perfect clue so most (not all) players guess the right surreal image card.", 
        R.drawable.your_pic
    

    )

    then try to put this value in your Game cons.