Android Kotlin 有条件地调用不同的和弃用的构造函数

Android Kotlin call different and deprecated constructor conditionally

我有一个用 Kotlin 编写的 Android 应用程序,其中 class BaseKeyListener 扩展了 DigitsKeyListener。我的最低 SDK 版本是 21。 class 当前正在调用已弃用的构造函数。然而,新的构造函数仅在 API 26 级及以上可用。 我如何根据 API 级别有条件地调用构造函数?

我基本上是在 前一段时间为 Android 发布的,但该解决方案似乎在 Kotlin 中不起作用。

在 Kotlin 中,我的 class 现在看起来像这样:

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

}

如果我应用 Android 问题的解决方案,我会得到以下代码:

abstract class BaseKeyListener : DigitsKeyListener {

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

还提供了另一种解决方案,我必须将构造函数设为私有并实现 newInstance 模式。但是我不能使用该解决方案,因为还有其他 class 继承自 BaseKeyListener 并且 BaseKeyListener 也是抽象的。

我唯一能想到的是:

abstract class BaseKeyListener : DigitsKeyListener {

   constructor()

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

但结果是我必须为每个子class定义两个构造函数。如果我使用 class 我每次都必须添加一个条件,而我们使用的 Locale 是相同的。

不幸的结果:

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()

理想的解决方案应该是在单行上分配 AmountKeyListener 并且 BaseKeyListener 应该知道何时使用我们的自定义语言环境 'MY_LOCALE'

editText.keyListener = KeyListenerUtil.AmountKeyListener()

如何解决这个问题?

您链接的 Java 解决方案基本上只是忽略弃用并专门使用弃用的构造函数。我认为你最后的解决方案是最好的。它的用法并不比直接使用 DigitsKeyListener 差——您仍然需要检查 SDK 版本。

我在上面看到的一个小问题是您的第一个构造函数隐式调用了空的超级构造函数,从而通过本质上是一种语言破解来避免了弃用警告。真的,在我看来,这似乎是 Kotlin 代码检查器中的一个错误。我认为显式调用超级构造函数并在您自己的 class 中弃用此构造函数会更合适。所以我会让它看起来像这样:

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)
}

这不会在功能上改变它的工作方式,但是在不弃用您的裸构造函数的情况下,很容易在任何地方意外使用弃用版本的 DigitsKeyListener。

并且在使用站点上,虽然很痛苦,但看起来就像上面那样,除了您还要在该行之前放置 @Suppress("DEPRECATION") 以确认弃用警告。