0

I'm newbie on android and kotlin. I'm making onclick listener for my cardViewAdapter using interface so i can override its callback from my activity. But I get the error "lateinit property onItemClick has not been initialized" when running it on emulator and clicked each itemView.

On my code, I tried to initialize it inside a function. Before that, I tried this answer from another so https://stackoverflow.com/a/46076355/7587265 but onclick doesn't work

this is my MainActivity.kt

rvMotor.layoutManager = GridLayoutManager(this, 2)
val recycleViewAdapter = CardViewMainAdapter(listMotor)
recycleViewAdapter.setOnItemClickCallback(object : CardViewMainAdapter.OnItemClickCallback{
    override fun onItemClicked(data: Motor) {
        val intent = Intent(this@MainActivity, DetailActivity::class.java)
        intent.putExtra(DetailActivity.EXTRA_ID, data.id)
        startActivity(intent)
    }
})

rvMotor.adapter = recycleViewAdapter

and this is my CardViewMainAdapter.kt

class CardViewMainAdapter(private val listMotors: ArrayList<Motor>) :
    RecyclerView.Adapter<CardViewMainAdapter.CardViewMainViewHolder>() {

    private lateinit var onItemClickCallback : OnItemClickCallback

    fun setOnItemClickCallback(onItemClickCallback: OnItemClickCallback){
        this.onItemClickCallback = onItemClickCallback
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CardViewMainViewHolder {
        val view: View = LayoutInflater.from(parent.context).inflate(R.layout.cardview_main, parent, false)
        return CardViewMainViewHolder(view)
    }

    override fun getItemCount(): Int {
        return listMotors.size
    }

    override fun onBindViewHolder(holder: CardViewMainViewHolder, position: Int) {
        val motor = listMotors[position]

        holder.cvMainName.text = motor.name
        Glide.with(holder.itemView.context)
            .load(motor.image)
            .apply(RequestOptions().override(350, 550))
            .into(holder.cvMainImage)

        holder.itemView.setOnClickListener{
            onItemClickCallback.onItemClicked(listMotors[holder.adapterPosition])
        }
    }

    inner class CardViewMainViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
        var cvMainImage: ImageView = itemView.findViewById(R.id.cardview_main_img)
        var cvMainName: TextView = itemView.findViewById(R.id.cardview_main_txt)
    }

    interface OnItemClickCallback {
        fun onItemClicked(data: Motor)
    }
}
Michiel Leegwater
  • 1,172
  • 4
  • 11
  • 27

2 Answers2

1

As per the doc : Accessing a lateinit property before it has been initialized throws a special exception that clearly identifies the property being accessed and the fact that it hasn't been initialized.

To check whether a lateinit var has already been initialized, use .isInitialized on the reference to that property:

I don't why it's causing the problem here. Your code is fine I think, but I can give you solution to your problem.

In your case you can solve your problem in two ways.

1. Just add an if condition in on clicks listener to check whether it is intilized or not.

 holder.itemView.setOnClickListener{

        //Check whether it is Initialized or not
        if(::onItemClickCallback.isInitialized){
            onItemClickCallback.onItemClicked(listMotors[holder.adapterPosition])
        }
    }

OR

2. remove lateint and make it as nullable.

    //Make it as nullable
    private  var onItemClickCallback : OnItemClickCallback? = null

    holder.itemView.setOnClickListener {

        holder.itemView.setOnClickListener {
            // add ? for handling nullable 
            onItemClickCallback?.onItemClicked(listMotors[holder.adapterPosition])
        }

    }
Happy Singh
  • 1,334
  • 9
  • 23
0

I ended up initializing onItemClickCallback inside adapter parameter, not from function. I thought i've tried this way, but for an unknown reason, it doesn't work before. Thanks for all responses. this is my activity

val recycleViewAdapter = CardViewMainAdapter(listMotor, object : CardViewMainAdapter.OnItemClickCallback{
            override fun onItemClicked(data: Motor) {
                val intent = Intent(this@MainActivity, DetailActivity::class.java)
                intent.putExtra(DetailActivity.EXTRA_ID, data.id)
                startActivity(intent)
            }
        })

rvMotor.adapter = recycleViewAdapter

this is my adapter

class CardViewMainAdapter(private val listMotors: ArrayList<Motor>, private val onItemClickCallback: OnItemClickCallback) :
    RecyclerView.Adapter<CardViewMainAdapter.CardViewMainViewHolder>() {