使用 Android 数据绑定创建双向绑定 [英] Create two-way binding with Android Data Binding

查看:94
本文介绍了使用 Android 数据绑定创建双向绑定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经实现了新的Android数据绑定,实现后发现它不支持双向绑定.我试图手动解决这个问题,但我正在努力寻找绑定到 EditText 时使用的好的解决方案.在我的布局中,我有这个视图:

I have implemented the new Android data-binding, and after implementing realised that it does not support two-way binding. I have tried to solve this manually but I am struggling to find a good solution to use when binding to an EditText. In my layout I have this view:

<EditText
android:id="@+id/firstname"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textCapWords|textNoSuggestions"
android:text="@{statement.firstName}"/>

另一个视图也显示了结果:

Another view is also showing the results:

<TextView
style="@style/Text.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{statement.firstName}"/>

在我的片段中,我像这样创建绑定:

In my fragment I create the binding like this:

FragmentStatementPersonaliaBinding binding = DataBindingUtil.inflate(inflater, R.layout.fragment_statement_personalia, container, false);
binding.setStatement(mCurrentStatement);

这有效并将 firstName 的当前值放在 EditText 中.问题是如何在文本更改时更新模型.我尝试在 editText 上放置一个 OnTextChanged-listener 并更新模型.这创建了一个循环杀死我的应用程序(模型更新更新 GUI,它调用 textChanged 次无穷大).接下来,我尝试仅在发生这样的真正变化时才通知:

This works and puts the current value of firstName in the EditText. The problem is how to update the model when the text changes. I tried putting an OnTextChanged-listener on the editText and updating the model. This created a loop killing my app (model-update updates the GUI, which calls textChanged times infinity). Next I tried to only notify when real changes occured like this:

@Bindable
public String getFirstName() {
    return firstName;
}

public void setFirstName(String firstName) {
        boolean changed = !TextUtils.equals(this.firstName, firstName);
        this.firstName = firstName;
        if(changed) {
            notifyPropertyChanged(BR.firstName);
        }
    }

这效果更好,但每次我写信时,GUI 都会更新,并且出于某种原因,编辑光标移到了前面.

This worked better, but everytime I write a letter, the GUI is updated and for som reason the edit-cursor is moved to the front.

欢迎任何建议

推荐答案

EDIT 04.05.16:Android 数据绑定现在自动支持两种方式绑定!只需替换:

EDIT 04.05.16: Android Data binding now supports two way-binding automatically! Simply replace:

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

与:

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

例如在 EditText 中,您将获得双向绑定.确保您更新到最新版本的 Android Studio/gradle/build-tools 以启用此功能.

in an EditText for instance and you get two-way binding. Make sure you update to the latest version of Android Studio/gradle/build-tools to enable this.

(以前的回答):

我尝试了 Bhavdip Pathar 的解决方案,但这未能更新我绑定到同一变量的其他视图.我通过创建自己的 EditText 以不同的方式解决了这个问题:

I tried Bhavdip Pathar's solution, but this failed to update other views I had bound to the same variable. I solved this a different way, by creating my own EditText:

public class BindableEditText extends EditText{

public BindableEditText(Context context) {
    super(context);
}

public BindableEditText(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public BindableEditText(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
}

private boolean isInititalized = false;

@Override
public void setText(CharSequence text, BufferType type) {
    //Initialization
    if(!isInititalized){
        super.setText(text, type);
        if(type == BufferType.EDITABLE){
            isInititalized = true;
        }
        return;
    }

    //No change
    if(TextUtils.equals(getText(), text)){
        return;
    }

    //Change
    int prevCaretPosition = getSelectionEnd();
    super.setText(text, type);
    setSelection(prevCaretPosition);
}}

使用此解决方案,您可以随心所欲地更新模型(TextWatcher、OnTextChangedListener 等),它会为您处理无限更新循环.使用此解决方案,模型设置器可以简单地实现为:

With this solution you can update the model any way you want (TextWatcher, OnTextChangedListener etc), and it takes care of the infinite update loop for you. With this solution the model-setter can be implemented simply as:

public void setFirstName(String firstName) {
    this.firstName = firstName;
    notifyPropertyChanged(BR.firstName);
}

这会在模型类中放置更少的代码(您可以将侦听器保留在您的 Fragment 中).

This puts less code in the model-class (you can keep the listeners in your Fragment).

如果您对我的问题有任何意见、改进或其他/更好的解决方案,我将不胜感激

I would appreciate any comments, improvements or other/better solutions to my problem

这篇关于使用 Android 数据绑定创建双向绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆