如何将对不同 variables/class 属性的引用作为方法参数而不是值?

How to put a reference to different variables/class properties as method parameter instead of a value?

我需要创建多个 editTexts 具有处理输入格式的逻辑。不同的 editTexts 将绑定到不同的变量并保存到 viewModel.home 的不同属性。但是,editTexts 将使用相同的逻辑(尽管字符串、整数、双精度等不同)因此我想避免复制粘贴代码。

对于每个 editText,我必须设置一个 addTextChangedListener 并重写 afterTextChanged 方法(见下文)。

我想通过从 afterTextChanged:

的每个覆盖调用另一个方法 (customAfterTextChanged()) 来尽可能多地概括
viewBinding.editTextAdress.addTextChangedListener(object: TextWatcher {
    override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
    override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
    override fun afterTextChanged(s: Editable?) {
        customAfterTextChanged()
}})

代码中的其他一些地方我将定义该方法:

        fun customAfterTextChanged () {
            if (viewBinding.adressEditText.text.toString() != "") {
                viewModel.home.adress = viewBinding.adressEditText.text.toString()
            }
        }

在上面的代码中,homeviewModel 是自定义 类 的实例,其中 home 作为实例存在于 viewModel 中。

我现在的问题是:我希望能够传入例如viewBinding.cityEditText而不是viewBinding.adressEditText到方法中。或者 viewModel.home.city 而不是 viewModel.home.adress。为了实现这一点,我认为需要用特定于方法的变量替换 viewBinding.editTextAdressviewModel.home.adress,并以某种方式将对 viewModel.home.city 的引用传递给变量。

但是,我不知道该怎么做。有人可以编辑我的代码以使其在此特定实例中工作吗?我想如果我能得到一个有效的例子,我就能够转化为所有其他逻辑。

有不同的方法可以完成您正在寻找的东西,但您受到以下事实的限制:您不能“通过引用”从 ViewModel 传递字符串之类的东西并像在 C++ 中那样修改它。 ()。您必须在 Kotlin/Java.

中使用稍微不同的模式

选项 1 - 使用回调

fun customAfterTextChanged(et: EditText, onResult: (String)->Unit) {
    val s = et.text.toString()
    if (s.isNotEmpty()) {
        onResult(s)
    }
}

那么你可以这样称呼它

customAfterTextChanged(viewBinding.adressEditText) { s ->
    viewModel.home.adress = s
}

customAfterTextChanged(viewBinding.cityEditText) { s ->
    viewModel.home.city = s
}

选项 2 - 移动到 ViewModel(更好)

通常最好尝试将所有逻辑移动到 ViewModel 以使其更易于测试。如果你这样做,如果使用 ktx 扩展

,你的视图层最终会看起来像这样(没有逻辑 - 它只是在文本更改时调用 ViewModel)
viewBinding.adressEditText.doAfterTextChanged { e ->
    e?.let { viewModel.changedAddress(it.toString()) }
}

并且在 ViewModel 中您将拥有

fun changedAddress(a: String) {
    if( a.isNotEmpty() ) home.adress = a
}

这样做的好处是可以更轻松地对应用程序的行为进行单元测试。例如,要测试用户删除文本是否具有预期效果,您只需要这样的东西(而不是完整的 UI 测试)

model.changedAddress("123")
assertEqual("123", model.home.address)
model.changedAddress("")
assertEqual("123", model.home.address)

如果您的检查器逻辑更复杂,您始终可以像选项 1 一样在 ViewModel 中组合该逻辑 - 但它不需要与实际视图有任何联系