Search code examples
androidandroid-databinding

What is the correct way to do two-way data binding on android?


i made a simple hello world for 2 way data binding and seams works perfectly (when write on editext, the textview update automatically), but all code found online like official documentation has much more code and complications like https://developer.android.com/topic/libraries/data-binding/two-way

this is my code:

public class MainActivity extends AppCompatActivity {
    public String pippo;
    public Boolean visible = true;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        DataBindingUtil.setContentView(this, R.layout.activity_main);

    }
}



<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>

        <variable
            name="pippo"
            type="String" />

        <variable
            name="visible"
            type="Boolean" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@={pippo}" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{pippo}"
            android:visibility="@{visible ? android.view.View.VISIBLE: android.view.View.GONE}" />

        <CheckBox
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:checked="@={visible}" />
    </LinearLayout>
</layout>

In particular documentation use this things but seams useless:

  • BaseObservable
  • @Bindable
  • code to Avoids infinite loops
  • notifyPropertyChanged

so, what wrong or missing with my code?


Solution

  • In the two-way data binding you need to create class that extends from BaseObservable, annotate getters with @Bindable and call notifyPropertyChanged in your setters as below:

    public class Person extends BaseObservable {
    
        private String name;
    
        Person(String name) {
            this.name = name;
        }
    
        @Bindable
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
            notifyPropertyChanged(BR.name);
        }
    
    }
    

    Then pass this class as a databinding layout variable of type Person.

    <?xml version="1.0" encoding="utf-8"?>
    <layout xmlns:android="http://schemas.android.com/apk/res/android">
    
        <data>
    
            <variable
                name="person"
                type="com.example.android......Person" />
        </data>
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">
    
            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="@={person.name}" />
    
            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="@{person.name}" />
        </LinearLayout>
    </layout>
    

    Note: change the class path in the type attribute.

    and then set this layout variable in your activity with setPerson()

    public class ExampleActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            DataBindingUtil.setContentView(this, R.layout.activity_example);
    
            ActivityExampleBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_example);
    
            mActivityMainBinding.setPerson(new Person(""));
        }
    }