Android Kotlin call different and deprecated constructor conditionally

Wirling :

I have an Android app written in Kotlin with a class BaseKeyListener that extends DigitsKeyListener. My minimum SDK version is 21. The class currently is calling a deprecated constructor. However the new constructor is only available from API level 26 and upwards. How would I call the constructor conditionally based on API level?

I basically posted the same problem a while ago for Android but the solution doesn't seem to work in Kotlin.

In Kotlin my class now looks like this:

// primary constructor 'DigitsKeyListener' shows lint warning about deprecation.
abstract class BaseKeyListener() : DigitsKeyListener() {

}

If I apply the solution for the Android question I get this code:

abstract class BaseKeyListener : DigitsKeyListener {

    // still results in deprecation warning
    constructor() : super()
}

An alternative solution was also provided were I had to make the constructors private and implement a newInstance pattern. However I can't use that solution because there are other classes that inherit from the BaseKeyListener and the BaseKeyListener is also abstract.

The only thing I can think of is this:

abstract class BaseKeyListener : DigitsKeyListener {

   constructor()

    @RequiresApi(Build.VERSION_CODES.O)
   constructor(locale: Locale) : super(locale)
}

But as a result I would have to define two constructors for each subclass. And were I use the class I would have to add a condition every time while the Locale that we use is the same.

Unfortunate result:

open class AmountKeyListener : BaseKeyListener {

    constructor() : super()

    @RequiresApi(Build.VERSION_CODES.O)
    constructor(locale: Locale) : super(locale)
}

// usage of the keyListener
editText.keyListener = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) KeyListenerUtil.AmountKeyListener(
        MY_LOCALE) else KeyListenerUtil.AmountKeyListener()

The ideal solution should be to assign the AmountKeyListener on a single line and the BaseKeyListener should know when to use our custom locale 'MY_LOCALE'

editText.keyListener = KeyListenerUtil.AmountKeyListener()

How to solve this problem?

Tenfour04 :

The Java solution you linked basically is just ignoring the deprecation and exclusively using the deprecated constructor. I think your last solution is the best one. Its usage is no worse than if you were using DigitsKeyListener directly--you'd still have to be checking the SDK version.

One minor issue I see above is that your first constructor implicitly calls the empty super constructor, and thereby avoids the deprecation warning through what is essentially a language hack. Really, this seems to me to be a bug in the code inspector of Kotlin. I think it would be more appropriate to explicitly call the super constructor and also deprecate this constructor in your own class. So I would make it look like this:

abstract class BaseKeyListener : DigitsKeyListener {

    @Suppress("DEPRECATION")
    @Deprecated("Use the constructor with a locale if on SDK 26+.")
    constructor(): super()

    @RequiresApi(Build.VERSION_CODES.O)
    constructor(locale: Locale) : super(locale)
}

This doesn't functionally change how it works, but without deprecating your bare constructor, it becomes very easy to use the deprecated version of DigitsKeyListener everywhere by accident.

And at the usage site, although painful, it would look like you have it above, except you would also put @Suppress("DEPRECATION") right before that line to acknowledge the deprecation warning.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=337131&siteId=1