无法将图像分配给Nullable ImageView

问题描述

如何将图像设置为ImageView?

我的应用程序的想法是根据RecyclerView中的数据类显示不同类型的RecyclerView的视图持有者。数据类如下:

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,pic = null)
data class Game(override val title: String,override val body: String,override val pic: ImageView?): Thing(title,pic)

此外,我还有一个MainFragment,我在其中手动添加数据。在这里,我试图给出游戏的名称和描述,还将特定的图像设置为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)
  }
}

我如何在game_pic所在的位置声明GameViewHolder:

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
    }
}

使用game_pic.setimageResource(R.drawable.alias) as ImageView后出现的错误是:

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

解决方法

该错误表明您的game_pic变量为空。

一种建议的解决方法是我看不到您的代码

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

构造ImageView并在非null实例上设置图像资源。 或者,您可以在game_pic方法中的某个位置初始化onCreateView,然后在此之后初始化mMoviesBooksGames

UPD:

  1. 您不应将您的视图声明为可为空。
  2. 您可以用其他方式设置图像资源。

首先,您在mGamePicImageView中初始化init,然后在bind中重写它。其次,您只能将可绘制的数据传递给视图持有者,而不是整个ImageView。

我建议您重新设计数据类:

data class Game(
    override val title: String,override val body: String,override val imageDrawable: Drawable)

然后在viewholder的bind方法中

mGamePicImageView.setImageDrawable(dataToBind.imageDrawable)

最后

private val mMoviesBooksGames = listOf( Game(
    "Dixit",ContextCompat.getDrawable(this.activity,android.R.drawable.alias))
    )

不是getDrawable的第一个参数是上下文,因此在此处传递片段的父活动。第二个参数是drawable的ID,我不确定是否需要前缀android.,因此也可以只尝试R.drawable.alias

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

像这样修改数据类

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

写完之后,像这样将代码替换到您的视图持有器中

data class Game(
    "Dixit",R.drawable.your_pic

然后尝试将此值放入您的游戏缺点中。