如何将对不同 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()
}
}
在上面的代码中,home
和 viewModel
是自定义 类 的实例,其中 home
作为实例存在于 viewModel
中。
我现在的问题是:我希望能够传入例如viewBinding.cityEditText
而不是viewBinding.adressEditText
到方法中。或者 viewModel.home.city
而不是 viewModel.home.adress
。为了实现这一点,我认为需要用特定于方法的变量替换 viewBinding.editTextAdress
和 viewModel.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 中组合该逻辑 - 但它不需要与实际视图有任何联系
我需要创建多个 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()
}
}
在上面的代码中,home
和 viewModel
是自定义 类 的实例,其中 home
作为实例存在于 viewModel
中。
我现在的问题是:我希望能够传入例如viewBinding.cityEditText
而不是viewBinding.adressEditText
到方法中。或者 viewModel.home.city
而不是 viewModel.home.adress
。为了实现这一点,我认为需要用特定于方法的变量替换 viewBinding.editTextAdress
和 viewModel.home.adress
,并以某种方式将对 viewModel.home.city
的引用传递给变量。
但是,我不知道该怎么做。有人可以编辑我的代码以使其在此特定实例中工作吗?我想如果我能得到一个有效的例子,我就能够转化为所有其他逻辑。
有不同的方法可以完成您正在寻找的东西,但您受到以下事实的限制:您不能“通过引用”从 ViewModel 传递字符串之类的东西并像在 C++ 中那样修改它。 (
选项 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 中组合该逻辑 - 但它不需要与实际视图有任何联系