【问题标题】:Can't assign an image to a Nullable ImageView无法将图像分配给 Nullable ImageView
【发布时间】:2020-08-18 11:17:38
【问题描述】:

如何将图像设置为 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, 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)

另外,我有一个 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

【问题讨论】:

  • 有错字吗?您没有设置第三个参数,因为它在与 body 相同的引号中
  • 你的game_pic 变量为空,你能把代码贴出来吗,你在哪里声明的?
  • @Steyrix,我添加了声明。我基本上在我的 RecyclerView 的 ViewHolder 中声明它。

标签: android kotlin android-recyclerview imageview android-imageview


【解决方案1】:
data class Game(
    override val title: String, 
    override val body: 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", 
    "Give the perfect clue so most (not all) players guess the right surreal image card.", 
    R.drawable.your_pic

)

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

【讨论】:

  • 嗨@Nik,非常感谢您的回答。您的代码有所帮助 - 它不再崩溃,谢谢!但无论如何我都没有看到我设置的图片。
  • 虽然,mGamePicImageView.setImageResource(dataToBind.pic) 不起作用,因为我在 GameViewHolder 类中初始化 mGamePicImageView = R.id.game_pic.setImageResource() 不适用于 Int 类型
  • 首先,检查是否使用了 android:src 属性的 XML 文件,如果是,则删除它并添加 android:scaleType=" center crop" 并尝试此 mGamePicImageView.setBackgroundResource( R.drwable.your_pic) 如果它不起作用然后更改可绘制图像可能图像已损坏
  • 非常感谢!您的解决方案帮助很大。只有我使用了dataToBind.pic?.let { mGamePicImageView?.setImageResource(it) },因为我在开头放了abstract class Thing(open val title: String, open val body: String, open val pic: Int?)
  • 我觉得你应该为类似的视图做一个扩展功能你不知道它对你有多大的用和惊喜,太神奇了,如果你不知道请在线参考
【解决方案2】:

错误表明您的 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 并设置图片资源。 或者你可以在某个地方初始化你的game_pic,例如onCreateView方法,然后再初始化你的mMoviesBooksGames

UPD:

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

首先,您在init 中初始化您的mGamePicImageView,然后在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", 
    "Give the perfect clue so most (not all) players guess the right surreal image card.", 
    ContextCompat.getDrawable(this.activity, android.R.drawable.alias))
    )

getDrawable 的第一个参数不是上下文,所以将片段的父活动传递给那里。第二个参数是drawable的id,我不确定你是否需要前缀android.,所以你也可以试试R.drawable.alias

【讨论】:

  • 崩溃与Attempt to invoke virtual method 'android.content.res.Resources android.content.Context.getResources()' on a null object reference
  • 我无法避免将 ImageView 设置为可空,因为我必须将它作为空放在我的其他数据结构中。
  • @Lilya 你不需要 imageview 参数,使用 drawable 代替。而且,数据类不应该对视图有任何了解,它们只代表设置给视图的数据,而不是视图本身
  • 确切地说,它们代表数据。 ImageView 是我传递来表示的数据
  • @Lilya ImageView 实际上是 View 的子类。 Nik 的回答向您推荐了我在回答中所写的类似内容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-02-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-13
相关资源
最近更新 更多