我如何遍历数据绑定器已知的所有视图?

How can I iterate over all views known to the data binder?

我的布局中有三个 TextInputEditText 视图,用户可以在其中输入特定信息。
单击 Button,此信息将存储在我的数据库中。

用户点击这个Button后,我想清除所有TextInputEditText字段。
现在,我正在通过硬编码来做到这一点:

private fun clearAllEditTextFields() {
        
    Timber.d("clearAllEditTextFields: called")
        
    binding.bookTitleEditText.text = null
    binding.bookAuthorEditText.text = null
    binding.bookPageCountEditText.text = null
        
}

因为这很糟糕,我想使用动态 for each 循环来识别 binding 已知的所有 TextInputEditText 类型的视图并清除它们的内容:

private fun clearAllEditTextFields() {
        
    Timber.d("clearAllEditTextFields: called")
        
    for (view in binding.views) {

        if (view is TextInputEditText) {

            view.text = null
        
        }

}

很遗憾,没有这样的字段binding.views
还有办法实现这个或具有相同属性的东西吗?

到目前为止我尝试了什么

我用过一个BindingAdapter。在我的 Util class 中,我创建了一个 EditText 扩展函数 clearText,注释为 BindingAdapterJvmStatic

@JvmStatic
@BindingAdapter("clearText")
fun EditText.clearText(@NotNull shouldClear: Boolean) {
        
    Timber.d("clearText: called")
        
    if (shouldClear) text = null
        
}

在XML中:

<com.google.android.material.textfield.TextInputEditText
    android:id="@+id/book_title_edit_text"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:imeActionId="100"
    android:imeOptions="actionNext"
    android:inputType="text"
    android:text="@={viewModel.bookTitle}"
    app:clearText="@{viewModel.clearAllEditTextFields}"
/>

在我的 ViewModel class 中,我创建了一个 var clearAllEditTextFields = false,它在 clearAllEditTextFields() 函数中进行了修改,该函数在我的 ViewModel 中被调用:

...
var clearAllEditTextFields = false
clearAllEditTextFields()
...

private fun clearAllEditTextFields() {
        
    Timber.d("clearAllEditTextFields: called")
        
    clearAllEditTextFields = true
        
}

根据Logcat,我的扩展函数在我的ViewModel初始化时被调用。但是,当 clearAllEditTextFields() 被调用时,它不会触发对扩展函数的新调用。

不存在用于遍历 binding 对象中的视图的简单 for 循环,您可以尝试以下操作以保持代码的简洁。

作用域函数

    binding.apply{
       bookTitleEditText.text = null
       bookAuthorEditText.text = null
       bookPageCountEditText.text = null
    }

scope 函数是一个很好的 iff 视图很少,如果视图数量很大,我们最终会得到相当多的 boiler-plate 代码,在这种情况下,我认为 Binding-Adapter 将是一个不错的选择

@BindingAdapter("clear_text")
fun EditText.clearText(shouldClear : Boolean?){
   shouldClear?.apply{
       if(shouldClear)
          text = null
   }
}

ViewModel

private val _shouldClear = MutableLiveData<Boolean>()
val shouldClear : LiveData<Boolean>
get() = _shouldClear

fun setClearStatus(status : Boolean){
   _shouldClear.value = status
}

//since clearing a text is an event and not state, reset the clear_status once it's done
fun resetClearStatus(){
  _shouldClear.value = nul
}

XML

<EditText 
  ......
  app:clear_text = "@{yourViewModel.shouldClear}"
  ...... />

ActivityClass

...
binding.lifecycleOwner = this
...


private fun clearAllEditTextFields() {
   yourViewModel.setClearStatus(true)
   yourViewModel.resetClearStatus()        
}

编辑:

在您的 activity class 中添加 binding.lifecycleOwner = this 并且它用于通过数据绑定观察 LiveData。该视图将在运行时观察文本更改。