101is5
101is5

Reputation: 369

Kotlin getString() exepects an Int? Why?

I'm going through https://developer.android.com/codelabs/basic-android-kotlin-training-project-lemonade. Here, while trying to make "else" do nothing, I've stumbled upon "Type mismatch" errors.
Regarding setting the view elements, this is what I've come up with so far:

private fun setViewElements() {
        val textAction: TextView = findViewById(R.id.text_action)
        val text = when (lemonadeState) {
            SELECT -> R.string.lemon_select
            SQUEEZE -> R.string.lemon_squeeze
            DRINK -> R.string.lemon_drink
            RESTART -> R.string.lemon_empty_glass
            else -> null
        }
        textAction.text = getString(text)

I've tried all workarounds for "doing nothing": {}, Unit, null, empty string (and even data types like String, Int, Double...) but all I get is a "Type mismatch: inferred type is Any but Int was expected" (or "...inferred type is Int?...") error. So much so that an Int does makes the error disapear, as in:

...
else -> 0

According to the docs, both versions of getString(), single and double paramater, work stritcly with strings: parameter(s) and return type. So why on Earth is it saying this function expects an Int?
Also, writing text as an instance of Int (text: Int), doesn't affect anything, meaning it is in fact an Int. I am missing something big here: aren't those R.string.<name> supposed to be strings?

Btw, I did try this:

private fun setViewElements() {
        val textAction: TextView = findViewById(R.id.text_action)
        val text = when (lemonadeState) {
            SELECT -> R.string.lemon_select
            SQUEEZE -> R.string.lemon_squeeze
            DRINK -> R.string.lemon_drink
            else -> R.string.lemon_empty_glass
        }
        textAction.text = getString(text)

which is errorless and looks better. However, I wanted to keep the specificity, if possible (and it doesn't answer my question).

Upvotes: 0

Views: 1691

Answers (1)

Sweeper
Sweeper

Reputation: 274490

As the comments pointed out, getString takes a Int, which is a resource ID. This identifies one of the strings you have written in your XML files. This way, you can easily have e.g. multiple versions of the string, one for each localisation for your app, and getString will figure out which string to use based on the device locale. R.string.lemon_select, R.string.lemon_squeeze etc are those identifiers.

One way to do nothing, is to return just evaluate to null - you just have to handle the null value yourself. This will cause text to be of type Int?.

val text = when (lemonadeState) {
    SELECT -> R.string.lemon_select
    SQUEEZE -> R.string.lemon_squeeze
    DRINK -> R.string.lemon_drink
    RESTART -> R.string.lemon_empty_glass
    else -> null
}

if (text != null) {
    textAction.text = getString(text)
}

From your last code snippet though, it seems like you want to set it to lemon_empty_glass when the else branch is reached. If that is the case, then you can do:

val text = when (lemonadeState) {
    SELECT -> R.string.lemon_select
    SQUEEZE -> R.string.lemon_squeeze
    DRINK -> R.string.lemon_drink
    RESTART -> R.string.lemon_empty_glass
    else -> null
}
textAction.text = getString(text ?: R.string.lemon_empty_glass)

Upvotes: 3

Related Questions