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

查看:423
本文介绍了使用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中.问题是当文本更改时如何更新模型.我尝试将OnTextChanged-listener放在editText上并更新模型.这创建了一个终止我的应用程序的循环(模型更新更新了GUI,该调用称为textChanged times infinity).接下来,我尝试仅在发生如下实际更改时通知:

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.

任何建议都将受到欢迎

推荐答案

编辑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天全站免登陆