LiveData双向数据绑定,不公开MutableLiveData

时间:2019-05-28 11:13:46

标签: android android-databinding android-architecture-components android-livedata

我正在尝试在EditText上使用双向数据绑定,如果我将该字段公开为MutableLiveData,那么效果很好,就像我在网上找到的示例中通常看到的那样。

但是,有充分的理由不公开MutableLiveData,并且这些理由并不是神奇的无效,因为我决定使用数据绑定库。

EDIT:这里的主要动机是MyViewModel应该保持对设置数据的控制(这就是为什么不建议直接公开MutableLiveData的原因),在设置器中,我可以执行任何必要的检查或转换,然后只需在LiveData上调用setValue

我通常会公开一个LiveData的getter和一个与ViewModel分开的setter,我试图通过使用InverseMethod()批注来实现双向数据绑定,但这实际上并没有用因为数据绑定正在寻找LiveData本身的getValue()的InverseMethod。

这是一个简单的例子:

public class MyViewModel extends ViewModel {

    private MutableLiveData<String> mEmail = new MutableLiveData<>();

    // @InverseMethod("setEmail")    ### THIS DOESN'T WORK
    public LiveData<String> getEmail() {
        return mEmail;
    }

    // ### I WANT DATA-BINDING TO USE THIS METHOD
    public void setEmail(String email) {
        if (mEmail.getValue() != email) {
            mEmail.setValue(email);
        }
    }
}

这就是想要绑定它的方式

<EditText
   android:id="@+id/input_email"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:text="@={viewmodel.email}"/>

到目前为止,唯一可行的解​​决方法是使用单向数据绑定在EditText上设置文本,然后附加TextWatcher并从此处调用ViewModel.setter。

编辑:
第二种解决方法是扩展MutableLiveData,然后在覆盖的setValue中进行检查和转换,这要编写很多样板。

3 个答案:

答案 0 :(得分:0)

我有完全相同的问题,那就是我如何找到您的问题。 我知道这不是您真正要寻找的东西,但一种选择是从ViewModel中观察mEmail,并在其中实现您的setEmail()代码(当然,值本身已经设置好了……我不知道)知道如何控制设置值,这正是我所寻找的)

val observer = Observer<String> { setEmail(it)}
fun setEmail(value:String){ //Your code }
init{
    mEmail.observeForever(observer)
}
//Don´t forget to remove the observer

答案 1 :(得分:0)

我们建议从ObservableField切换到LiveData进行数据绑定,因为它具有生命周期意识。我们还建议不要公开MutableLiveData,因为视图模型应控制分配。

这非常适合单向数据绑定,在这种情况下,我只会公开LiveData。

我们要使用双向数据绑定,根据定义,该绑定将分配从视图模型移动到UI,因此我认为在这种情况下公开MutableLiveData是正确的。我说这是因为我们故意这样做,因为我们希望我们的UI能够分配值,以便我们获得更清晰的视图。

答案 2 :(得分:0)

我已经把这个问题忘了一段时间了,但是作为一种解决方法,我稍微扩展了- name: Enable pgcrypto extension run: | PGPASSWORD=helloworl psql -U postgres -tc "CREATE EXTENSION 'pgcrypto';" 并在每次需要控制设置器时使用它。

MutableLiveData

现在按如下方式使用import androidx.core.util.Consumer; import androidx.lifecycle.MutableLiveData; public class DelegatedMutableLiveData<T> extends MutableLiveData<T> { private Delegate<T> mDelegate; public interface Delegate<T> { void onSet(T value, Consumer<T> setter); } public DelegatedMutableLiveData(Delegate<T> delegate) { mDelegate = delegate; } public DelegatedMutableLiveData(T value, Delegate<T> delegate) { super(value); mDelegate = delegate; } @Override public void setValue(T value) { if (mDelegate != null) { mDelegate.onSet(value, super::setValue); } else { super.setValue(value); } } }

DelegatedMutableLiveData