Search code examples
androidobserver-patternandroid-databinding

how to be notified in view in Databinding library?


Hi my problem is that my activity listening for viewmodel field changes but callback not get called!

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ActivityMainBinding binding = DataBindingUtil.setContentView(this,R.layout.activity_main);
    binding.addOnPropertyChangedCallback(new Observable.OnPropertyChangedCallback() {
        @Override
        public void onPropertyChanged(Observable observable, int i) {
            Log.d(getClass().getSimpleName(), "changed");
        }
    });
    User user = new User("user");
    binding.setUser(user);
    user.setName("newUser");
    }

}

and my viewModel:

public class User extends BaseObservable {

    public String name;

    public User(String name) {
        this.name = name;
    }

    @Bindable
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
        notifyPropertyChanged(BR.name);
    }

}

UI updated but callback not get called. I want a callback plus UI update. I want to know data binding library works like this! there is Libraries like Rxjava for this but I don't like to import it.


Solution

  • When you do this:

    ActivityMainBinding binding = DataBindingUtil.setContentView(this,R.layout.activity_main);
    binding.addOnPropertyChangedCallback(new Observable.OnPropertyChangedCallback() {
        @Override
        public void onPropertyChanged(Observable observable, int i) {
            Log.d(getClass().getSimpleName(), "changed");
        }
    });
    User user = new User("user");
    binding.setUser(user);
    user.setName("newUser");
    

    You should receive one notification on the callback you provided and it should be received when you call binding.setUser(user). Look for ActivityMainBinding.java and you will see the code generated for the class in your app's build folder. In the setUser() method, you'll see the call to notifyPropertyChanged(BR.user) that will call your listener.

    The problem you're seeing is that the data change you want (name) is happening on the User and not on the Binding. In order to get notifications on changes to the user, you must add a lister like this:

    ActivityMainBinding binding = DataBindingUtil.setContentView(this,R.layout.activity_main);
    User user = new User("user");
    user.addOnPropertyChangedCallback(new Observable.OnPropertyChangedCallback() {
        @Override
        public void onPropertyChanged(Observable observable, int i) {
            Log.d(getClass().getSimpleName(), "changed");
        }
    });
    binding.setUser(user);
    user.setName("newUser");
    

    Anything implementing the Observable interface will support any number of listeners, so you can feel free to listen for events.