Home > Enterprise >  How to solve this Error:Unresolved reference: text which is related to scope in Kotlin?
How to solve this Error:Unresolved reference: text which is related to scope in Kotlin?

Time:09-27

What I want to achieve:

I want to get the button text as parameter for the function

What I want:

// Operators - setOnClickListener
btnDivide.setOnClickListener { viewModel.mountOperator(it.text) }
btnMultiply.setOnClickListener { viewModel.mountOperator(it.text) }
btnMinus.setOnClickListener { viewModel.mountOperator(it.text) }
btnPlus.setOnClickListener { viewModel.mountOperator(it.text) }

What is working:

// Operators - setOnClickListener
btnDivide.setOnClickListener { viewModel.mountOperator(btnDivide.text) }
btnMultiply.setOnClickListener { viewModel.mountOperator(btnMultiply.text) }
btnMinus.setOnClickListener { viewModel.mountOperator(btnMinus.text) }
btnPlus.setOnClickListener { viewModel.mountOperator(btnPlus.text) }

The problem that is appearing:

Error: Unresolved reference: text, when i am doing it.text
But inside setOnClickListener{ it: View! }, I saw this preview as it is generally shown. So I thought that, here it is refering to the button to which I am setting the onClickListener.

if there is any confusion about the question, please write in the comment. If my approach is wrong, share in the comments

CodePudding user response:

So I thought that, here it is referring to the button to which I am setting the onClickListener.

Here, it is of type View and not of type Button, or whatever type of specific view type you want it to be, so because not all views have a text property (which means that View doesn't have something called text, but Button might), you can use something like this:

 btnDivide.setOnClickListener { viewModel.mountOperator((it as Button).text) } 

where you can replace Button with whatever type of view it is.

it as Button is casting the View we get into our specific type, in your case I'm assuming this will be a button, but you can cast it to whatever type of view it actually is.


it: View! here does refer to the button you're setting the onClickListener to, but it's returned to you as a View and not of a more specific type

CodePudding user response:

Also to follow up on @a_local_nobody's answer, the reason it's just passing in a generic View and not the type you're setting the click listener on, is because you can create a single listener object/function and reuse it for all the things that need to handle clicks (which could be different subclasses of View)

So if you like, you could make one of those and use it instead of repeating the code for each button:

fun handleButtonClick(view: View) {
    if (view is Button) viewModel.mountOperator(view.text)
}

btnDivide.setOnClickListener { handleButtonClick(it) }
// or as a function reference
btnMultiply.setOnClickListener(::handleButtonClick)

And another thing you can do when you're assigning multiple identical click listeners (or doing the same anything to a bunch of things) is to just do a loop

listOf(btnDivide, btnMultiply, btnMinus, btnPlus).forEach {
    it.setOnClickListener { //bla bla }
}

that works for reusing a function reference or just creating a new one for each listener (like you're doing in your question) - it just saves you repeating yourself, it can be easier to read, and if you need to make changes you only have to do it in one place

  • Related