1

使用 Android 双向数据绑定时,我是否必须在上使用 staticBindingAdapter或者View是否可以简单地使用可观察的实例字段?在文档中,我总是只在ViewModels 上看到可观察字段,而不是在View. 我尝试在我View的 with上实现可观察字段

var myValue: String = ""
@Bindable get(): String {
    return field
}
set(value: String) {
    field=value
    setText(value)
    notifyPropertyChanged(BR.myValue) // my View implements the Observable interface
}

但是当我编译这个(./gradlew assembleDebug --stacktrace获取详细信息)时,它失败了

ERROR: Cannot find a getter for <com.example.test.MyAutoCompleteTextView app:myValue> 
that accepts parameter type 'java.lang.String'

If a binding adapter provides the getter, check that the adapter is annotated correctly
and that the parameter type matches. 

那么,是否可以View像在双向数据绑定上那样使用可观察字段ViewModel?我想使用可观察字段而不是 staticBindingAdapter的原因是我View有一些比我可以处理的更复杂的逻辑/状态BindingAdapter(好吧,从静态BindingAdapter我可以调用到myViewInstance.myValue,但不知何故我感觉不对)

更新

我构建了一个最小(非)工作示例,可在 Github 上找到 。默认情况下,它使用单向绑定,效果很好。改变

app:myValue="@{viewModel.realValue}"

app:myValue="@={viewModel.realValue}"

inactivity_main.xml将导致信息量不大的编译错误。用于./gradlew assembleDebug --stacktrace获得长输出,其中包括

ERROR: Cannot find a getter for 
<com.example.test.MyAutoCompleteTextView app:myValue> 
that accepts parameter type 'java.lang.String'

谁能看看这个,让我知道我做错了什么?

4

1 回答 1

1

使用 Android 双向数据绑定时,我是否必须在视图上使用静态 BindingAdapters,或者是否可以简单地使用可观察的实例字段?

我认为您很有可能使用 Observable 实例字段来做到这一点。但是,如果这个逻辑也在其他地方被重用,我个人更喜欢使用BindingAdapters.

在您的 Observable 类中,将您的代码修改为:

@get:Bindable
var myValue: String = ""
    set(value) {
        field = value 
        notifyPropertyChanged(BR.myValue) // my View implements the Observable interface
    }

我检查了您的存储库并意识到您现在正在使用 MutableLiveData,因此在这种情况下您不需要上述代码。我在那里也找不到任何 BindingAdapter。确保您的代码 BindingAdapter 看起来像这样:

@BindingAdapter("myValue")
@JvmStatic
fun TextView.setMyValue(realValue: String) {
    val finalValue : String = realValue.dataManipulation() // Do your data manipulation here
    setText(finalValue) // Make sure it's a string
}

最后,您在 XML 中的 TextView 应该如下所示:

<com.example.test.MyAutoCompleteTextView
    ...
    app:myValue="@{viewModel.realValue}"
    ... />

让我知道这是否有效。



编辑

所以我们要找的基本上是 BaseObservable 类中的 Bindable 变量。让我们关注三件事:您的 XML、您的活动/片段和您的 BindingModel 类。

您的 BindingModel 类基本上扩展了您的 BaseObservable 类。

class BindingModel: BaseObservable(){
    @get:Bindable
    var myValue: String = ""
        set(value) {
            var finalValue = manipulateData(value) //Write your logic here
            field = finalValue
            notifyPropertyChanged(BR.myValue) // my View implements the Observable interface
    }
...
}

在您的 Activity/Fragment 中,创建一个类型为 的变量BindingModel。观察您的 LiveData 并更新变量。

class MainActivity : AppCompatActivity() {
...
val model = BindingModel()
...
override fun onCreate(savedInstanceState: Bundle?) {
    ...
    binding.lifecycleOwner = this // Specify the current activity as the lifecycle owner.
    binding.model = model
    viewModel.realValue.observe(this, Observer {
        model.myValue = it
    })
} // End of onCreate()
...
} // End of Activity code

继续您的 XML,您需要在其中声明model数据绑定变量。

...
<data>
...
<variable
    name="model" //Make sure the name is same
    type="com.example.test.<path-to-your-file>.BindingModel" />
</data>
...
<com.example.test.MyAutoCompleteTextView
...
android:text="@{model.realValue}" //Don't forget this
... />

瞧!它应该工作。如果没有,请告诉我。

于 2020-04-21T15:03:13.073 回答