实时数据和 2 向数据绑定:自定义 setter 未被调用

Live Data and 2-Way Data Binding: Custom setter not being called

我正在使用 2 向数据绑定来使用 EditText 中设置的字符串从我的 ViewModel 更新 LiveData String 对象:

<android.support.design.widget.TextInputEditText
  android:id="@+id/writeReviewTitle"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:text="@={viewModel.liveReviewTitle}"
/>

因此,根据我的理解,每次 EditText 中的文本更改时,ViewModel 都会更新其 liveReviewTitle 属性。我假设这是通过使用 TextWatcher 或图书馆为我处理的某种监听机制而发生的。我还认为,当需要更新文本时,它会调用 setter好像不是这样!当文本更改时,我需要在我的 ViewModel 中做更多的事情,因此我为 liveReviewTitle 实现了自定义 setter,但它 未被调用 (我试过调试)。 这是 ViewModel class:

中的样子
var liveReviewTitle: MutableLiveData<String> = MutableLiveData()
        set(value) {
            field = value
            customLogicHere()
        }

尝试调试此 setter 但它似乎从未被调用过!这里发生了什么?感觉有点混乱。正文正在更新中,保存在ViewModel,只是setter没有调用

当然它从来没有被调用过,你不是在设置一个新的 MutableLiveData,你是在 MutableLiveData 中设置一个新的字符串值(可能与 setValue)。

但是,如果您直接公开 MediatorLiveData 而不是 MutableLiveData,您应该能够拦截正在设置的值并在设置值后执行自定义逻辑。

编辑: 以下应该按预期工作:

val liveReviewTitle: MutableLiveData<String> = MutableLiveData()
private val mediator = MediatorLiveData<String>().apply {
    addSource(liveReviewTitle) { value ->
        setValue(value)
        customLogicHere()
    }
}.also { it.observeForever { /* empty */ } }

@EpicPandaForce 关于你的 setter 是正确的,它是针对 MutableLiveData 本身而不是它所持有的价值。所以你的 LiveData 应该是 val,不需要是 var,只要你在捆绑。您可以将另一个 Observer 添加到您的 LiveData 以代替自定义 setter 以添加您的自定义逻辑。

@EpicPandaForce 解决方案是正确的,但在 EditText 中,可以通过更简单的方式获得两种方式的绑定。 将属性 afterTextChanged 添加到您的小部件,如下所示:

android:afterTextChanged="@{viewModel::doLogic}"

然后在你的ViewModelclass中写方法:

fun doLogic(s: Editable) { //update Livedata or do other logic }

编辑

我错过了重要的文档 note。更容易(也更合适)将是:

android:text="@={viewModel.someLivedata}

然后在我们的 LifecycleOwner class 中,我们可以在需要时随时更新 liveData 的值,当然我们可以对注册观察者的更改做出反应。