Android Data Binding on Individual Views Added to LinearLayout Programmatically?
Asked Answered
R

1

10

I am able to get "activity-wide" data binding to work without any difficulties whatsoever. However, when I try to setup bindings for specific Views, say inflated Views that I'm programmatically adding to a LinearLayout, nothing I've tried works.

For example, binding data to an Activity's view is trivial. Typically in the onCreate() method one just has to add:

MainActivityBinding binding = DataBindingUtil.setContentView(this, R.layout.main_activity);
User user = new User("Test", "User");
binding.setUser(user);

That's it! The view main_activity.xml will be "bound" to the binding through some magic (this is my problem) and variable substitution will work as expected in the main_activity.xml.

I consulted Google's documentation regarding RecyclerView use and attempted to utilize this method in my inflated Views. I did this by creating a ListItemBinding (my .xml is just called list_item.xml and this file is auto-generated off of the .xml layout) for each ViewHolder, the ListItemBinding is passed in to the ViewHolder to be held as a reference through the Constructor of each ViewHolder.

Now of course this does not work, and I am guessing that the reason for this is that there's no explicit tie between my View and the Binding, however, there's no tie between the Activity above and the Binding either, so why does that work?

I'm digging into the source code to see how the binding works on Activities, I'm sure that will have my answer, but if anyone else can chime in before I spend multiple hours, I would appreciate the head-start!

I will report all findings here, thank you very much

Ridgeway answered 14/4, 2016 at 21:57 Comment(2)
There are some tricks to using Android Data Binding with RecyclerView. Take a look at this talk realm.io/news/data-binding-android-boyar-mount -- around 22 minutes in, Yigit speaks about how to use data binding with RecyclerView.Commitment
@GeorgeMount I actually did not want to use a RecyclerView as there is only 5 views max per list, so not a lot of recycling to be done... Anyway, I did switch to proper RecyclerViews over using a LinearLayout and adding the views individually to it. It was very easy and the extra overhead is probably worth the straight-forward approach.Ridgeway
C
19

You can add dynamically-inflated data bound views to a LinearLayout. You will have to programmatically set the data for the data bound view.

void addViewToViewGroup(ViewGroup viewGroup, User user) {
  LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());
  MyLayoutBinding binding = MyLayoutBinding.inflate(inflater, viewGroup,true);
  binding.setUser(user);
}

If there is a known Binding that you're attaching to, you can pull the data from there instead. Here, I assume the containing ViewGroup is in a layout outer.xml and generated binding OuterBinding.

void addViewToViewGroup(ViewGroup viewGroup) {
  OuterBinding outer = DataBindingUtil.findBinding(viewGroup);
  LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());
  MyLayoutBinding binding = MyLayoutBinding.inflate(inflater, viewGroup, true);
  binding.setUser(outer.getUser());
}

You can see that there is no direct binding between the OuterBinding's user and MyLayoutBinding's user. That means that if you update it, you won't see it reflected. With included layouts, the framework does work to bind it that you have to do manually. To get dynamic updates, you can do it this way:

outer.addOnPropertyChangedCallback(new OnPropertyChangedCallback() {
   @Override
   public void onPropertyChanged(Observable sender, int propertyId) {
       if (propertyId == BR.user) {
           binding.setUser(outer.getUser());
           break;
       }
   }
});
Commitment answered 10/5, 2016 at 23:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.