1

我正在尝试覆盖 Kotlin 中的 View.setRotation() 方法。

由于 AndroidKTX 已经提供了属性扩展“旋转”,调用者可以简单地调用

viewObject.rotation = 90.0f

旋转视图。

但是,我想在用户更改旋转时添加一些额外的操作,比如

override fun setRotation(newRotation: Float) {
    if (rotation == newRotation)
        return
    rotation = newRotation
    doSomethingElse()
}

由于 StackOverflow 错误,这将崩溃。

所以,我必须添加一些额外的代码来实现这个目标:

    private var _rotation: Float = 0.0f
    override fun setRotation(newRotation: Float) {
        if (_rotation == newRotation) {
            return
        }
        _rotation = newRotation
        updateRotationInternally()
    }

    private fun updateRotationInternally() {
        super.setRotation(_rotation)
        doSomethingElse()
    }

这行得通,但我想知道是否还有其他更优雅的方法,比如“覆盖属性扩展设置器”?

4

1 回答 1

2

我不同意您实施的一个方面:您的return快捷方式。您假设setRotation()使用现有旋转值调用无效。如果在 Google 的官方版本中确实如此,我不会感到惊讶View,但据我们所知,在某些运行 Android 8.0 修改版的 Oppo 设备上,这并不是一个安全的假设。尽量不要假设不是你写的东西的行为。如果您想doSomethingElse()在新旧旋转相等时跳过,那很好。

我猜你的setRotation()函数在View. 如果是这样,并考虑到我的上述投诉,这是我能想到的最简单的方法:

class Bar : View() {
  override fun setRotation(f: Float) {
    val needSomething = getRotation() != f

    super.setRotation(f)

    if (needSomething) doSomethingElse()
  }

  fun doSomethingElse() {
    println("got here!")
  }
}

我的整体测试代码是在Kotlin 暂存器(Android 之外)中完成的,所以我使用假View实现和假rotation扩展属性进行了测试:

open class View {
  private var r: Float = 0.0f

  open fun setRotation(f: Float) {
    r = f
  }

  fun getRotation() = r
}

var View.rotation: Float
  get() = getRotation()
  set(value) = setRotation(value)

class Bar : View() {
  override fun setRotation(f: Float) {
    val needSomething = getRotation() != f

    super.setRotation(f)

    if (needSomething) doSomethingElse()
  }

  fun doSomethingElse() {
    println("got here!")
  }
}

fun main() {
  val bar = Bar()

  bar.rotation = 15.0f
  bar.rotation = 15.0f
}

如果您在该暂存器中运行它,您将got here在控制台上看到一次打印,表明虽然我们成功更新了两次扩展属性,但我们getSomethingElse()在第二次调用时跳过了,因为新旧轮换是相同的。

于 2020-04-18T13:33:23.507 回答