Kotlin Annotation IntDef

2019-01-15 12:41发布

问题:

I have this code sample:

class MeasureTextView: TextView {
    constructor(context: Context?) : super(context)
    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes)

    companion object{
        val UNIT_NONE = -1
        val UNIT_KG = 1
        val UNIT_LB = 0            
    }

    fun setMeasureText(number: Float, unitType: Int){

        val suffix = when(unitType){
            UNIT_NONE -> {
                EMPTY_STRING
            }
            UNIT_KG -> {
                KG_SUFIX
            }
            UNIT_LB -> {
                LB_SUFIX
            }
            else -> throw IllegalArgumentException("Wrong unitType passed to formatter: MeasureTextView.setMeasureText")
        }

        // set the final text
        text = "$number $suffix"
    }
}

I want to be able to use, at compile time, the auto complete feature in conjunction with IntDef annotation, so when i invoke setMeasureText(...), the static variables are shown as options to the argument of this method.

I have searched about this, and i couldn't find if Kotlin supported this java-style annotations (intdef for example). So i have tried it, and made an annotation for this, but it won't show in autocompletion.

My question: - Is Java annotation IntDef supported in Kotlin (latest version)

  • If it is, how can i turn in ON in the Android Studio IDE (if it works, i can't get the compiler to suggest it).

  • If it is not, is there any Kotlin-way of make this compile time checks

回答1:

As of Kotlin 1.0.3, the @IntDef annotation is not supported, but support is planned for later versions.

The Kotlin way of making these compile time checks is to use an enum class instead of a series of Int constants.



回答2:

Strange thing, but this question comes in search before the same with right answer

Copying it here:

import android.support.annotation.IntDef
public class Test {

    companion object {

         @IntDef(SLOW, NORMAL, FAST)
         @Retention(AnnotationRetention.SOURCE)
         annotation class Speed

         const val SLOW = 0
         const val NORMAL = 1
         const val FAST = 2
    }

    @Speed
    private var speed: Int=SLOW

    public fun setSpeed(@Speed speed: Int) {
        this.speed = speed
    }
}


回答3:

If you are calling setMeasureText from Java you can get it to work by creating your IntDef in Java too

// UnitType.java
@Retention(RetentionPolicy.SOURCE)
@IntDef({MeasureText.UNIT_KG, MeasureText.UNIT_LB, MeasureText.UNIT_NONE})
public @interface UnitType {}

h/t Tonic Artos

You will also need to update your companion object to make your values longs and publicly accessible

companion object{
    const val UNIT_NONE = -1L
    const val UNIT_KG = 1L
    const val UNIT_LB = 0L
}


回答4:

My preferred way to use IntDef with Kotlin is to use top-level declarations:

package com.example.tips


const val TIP_A = 1
const val TIP_B = 2
const val TIP_C = 3

@IntDef(TIP_A, TIP_B, TIP_C)
@Retention(AnnotationRetention.SOURCE)
annotation class TipId


class TipsDataProvider {

    fun markTip(@TipId tipId: Int) {
    ...
    }
}

No extra class or object required! More info about top-level declarations here.